bug fixes, added localize, minor ui improvements
|
@ -25,7 +25,7 @@ EnRecipes is an easy to use, privacy-friendly digital cookbook that lets you cre
|
||||||
- Add photo, notes and combinations to your recipes
|
- Add photo, notes and combinations to your recipes
|
||||||
- Organise your recipes by category
|
- Organise your recipes by category
|
||||||
- Quickly search for your recipes
|
- Quickly search for your recipes
|
||||||
- Mark recipes as favorites and add them to your Try Later list
|
- Mark recipes as favourites and add them to your Try Later list
|
||||||
- Scale your recipe ingredients to serve more or less people
|
- Scale your recipe ingredients to serve more or less people
|
||||||
- Get notified of the last time you tried a recipe
|
- Get notified of the last time you tried a recipe
|
||||||
- Share your recipe to anyone by any means as a nicely formatted message. You can share the recipe photo too.
|
- Share your recipe to anyone by any means as a nicely formatted message. You can share the recipe photo too.
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<string name="app_name">EnRecipes</string>
|
|
||||||
<string name="title_activity_kimera">EnRecipes</string>
|
|
||||||
</resources>
|
|
114
app/app.scss
|
@ -1,7 +1,6 @@
|
||||||
// NativeScript core theme
|
// NativeScript core theme
|
||||||
// @see https://docs.nativescript.org/ui/theme
|
// @see https://docs.nativescript.org/ui/theme
|
||||||
@import "~@nativescript/theme/core";
|
@import "~@nativescript/theme/core"; // Override variables here
|
||||||
// Override variables here
|
|
||||||
$gray1: #f1f3f5;
|
$gray1: #f1f3f5;
|
||||||
$gray2: #e9ecef;
|
$gray2: #e9ecef;
|
||||||
$gray3: #dee2e6;
|
$gray3: #dee2e6;
|
||||||
|
@ -17,20 +16,17 @@ $red: #c92a2a;
|
||||||
$breakfast: #ffb180;
|
$breakfast: #ffb180;
|
||||||
$lunch: #ceff80;
|
$lunch: #ceff80;
|
||||||
$dinner: #80ceff;
|
$dinner: #80ceff;
|
||||||
$snacks: #b180ff;
|
$snacks: #b180ff; // Global SCSS styling
|
||||||
|
|
||||||
// Global SCSS styling
|
|
||||||
// @see https://docs.nativescript.org/ui/styling
|
// @see https://docs.nativescript.org/ui/styling
|
||||||
|
.ns-modal,
|
||||||
Page,
|
Page {
|
||||||
.ns-modal {
|
font-family: 'Orkney-Regular';
|
||||||
font-family: "Orkney-Regular";
|
|
||||||
}
|
}
|
||||||
.orkm {
|
.orkm {
|
||||||
font-family: "Orkney-Medium";
|
font-family: 'Orkney-Medium';
|
||||||
}
|
}
|
||||||
.bx {
|
.bx {
|
||||||
font-family: "boxicons";
|
font-family: 'boxicons';
|
||||||
font-size: 24;
|
font-size: 24;
|
||||||
vertical-alignment: center;
|
vertical-alignment: center;
|
||||||
&.small {
|
&.small {
|
||||||
|
@ -39,38 +35,37 @@ Page,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.ns-light {
|
.ns-light {
|
||||||
Page,
|
|
||||||
ActionBar,
|
ActionBar,
|
||||||
|
ListPicker,
|
||||||
|
Page,
|
||||||
SearchBar,
|
SearchBar,
|
||||||
Tabs,
|
|
||||||
TabStripItem,
|
TabStripItem,
|
||||||
ListPicker {
|
Tabs {
|
||||||
color: $gray9;
|
color: $gray9;
|
||||||
background: $gray1;
|
background: $gray1;
|
||||||
}
|
}
|
||||||
MDRipple,
|
MDButton,
|
||||||
MDButton {
|
MDRipple {
|
||||||
ripple-color: rgba($gray6, 0.2);
|
ripple-color: rgba($gray6, 0.2);
|
||||||
}
|
}
|
||||||
.hr {
|
.hr {
|
||||||
border-color: $gray3;
|
border-color: $gray3;
|
||||||
}
|
}
|
||||||
.sd,
|
.fieldLabel,
|
||||||
.fieldLabel {
|
.sd {
|
||||||
background: $gray1;
|
background: $gray1;
|
||||||
}
|
}
|
||||||
.urlCard,
|
|
||||||
.textCard,
|
|
||||||
.overviewItem,
|
.overviewItem,
|
||||||
.recipeItem {
|
.recipeItem,
|
||||||
|
.textCard,
|
||||||
|
.urlCard {
|
||||||
background: white;
|
background: white;
|
||||||
}
|
}
|
||||||
TextField.combinationToken {
|
TextField.combinationToken {
|
||||||
background: $gray3;
|
background: $gray3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sd-item,
|
|
||||||
.sd-group-header,
|
.sd-group-header,
|
||||||
|
.sd-item,
|
||||||
.time .bx {
|
.time .bx {
|
||||||
color: $gray8;
|
color: $gray8;
|
||||||
}
|
}
|
||||||
|
@ -87,8 +82,8 @@ Page,
|
||||||
color: $gray1;
|
color: $gray1;
|
||||||
background: $gray9;
|
background: $gray9;
|
||||||
}
|
}
|
||||||
.instruction,
|
.dayContainer,
|
||||||
.dayContainer {
|
.instruction {
|
||||||
border-color: $gray9;
|
border-color: $gray9;
|
||||||
}
|
}
|
||||||
MDProgress {
|
MDProgress {
|
||||||
|
@ -101,14 +96,13 @@ Page,
|
||||||
background: $orange;
|
background: $orange;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ns-dark {
|
.ns-dark {
|
||||||
Page,
|
|
||||||
ActionBar,
|
ActionBar,
|
||||||
|
ListPicker,
|
||||||
|
Page,
|
||||||
SearchBar,
|
SearchBar,
|
||||||
Tabs,
|
|
||||||
TabStripItem,
|
TabStripItem,
|
||||||
ListPicker {
|
Tabs {
|
||||||
color: $gray1;
|
color: $gray1;
|
||||||
background: $gray9;
|
background: $gray9;
|
||||||
}
|
}
|
||||||
|
@ -116,27 +110,26 @@ Page,
|
||||||
// tab-background-color: $gray9;
|
// tab-background-color: $gray9;
|
||||||
// selected-tab-text-color: $gray1;
|
// selected-tab-text-color: $gray1;
|
||||||
// }
|
// }
|
||||||
MDRipple,
|
MDButton,
|
||||||
MDButton {
|
MDRipple {
|
||||||
ripple-color: rgba($gray4, 0.1);
|
ripple-color: rgba($gray4, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.hr {
|
.hr {
|
||||||
border-color: #111;
|
border-color: #111;
|
||||||
}
|
}
|
||||||
.sd,
|
.fieldLabel,
|
||||||
.fieldLabel {
|
.sd {
|
||||||
background: $gray9;
|
background: $gray9;
|
||||||
}
|
}
|
||||||
.urlCard,
|
|
||||||
.textCard,
|
|
||||||
.overviewItem,
|
.overviewItem,
|
||||||
.recipeItem,
|
.recipeItem,
|
||||||
|
.textCard,
|
||||||
|
.urlCard,
|
||||||
TextField.combinationToken {
|
TextField.combinationToken {
|
||||||
background: $gray8;
|
background: $gray8;
|
||||||
}
|
}
|
||||||
.sd-item,
|
|
||||||
.sd-group-header,
|
.sd-group-header,
|
||||||
|
.sd-item,
|
||||||
.time .bx {
|
.time .bx {
|
||||||
color: $gray3;
|
color: $gray3;
|
||||||
}
|
}
|
||||||
|
@ -153,8 +146,8 @@ Page,
|
||||||
color: $gray9;
|
color: $gray9;
|
||||||
background: $gray1;
|
background: $gray1;
|
||||||
}
|
}
|
||||||
.instruction,
|
.dayContainer,
|
||||||
.dayContainer {
|
.instruction {
|
||||||
border-color: $gray1;
|
border-color: $gray1;
|
||||||
}
|
}
|
||||||
MDProgress {
|
MDProgress {
|
||||||
|
@ -176,7 +169,7 @@ TimePickerField {
|
||||||
border-width: 1;
|
border-width: 1;
|
||||||
font-size: 14;
|
font-size: 14;
|
||||||
padding: 14 14 13;
|
padding: 14 14 13;
|
||||||
margin: 8 0 0 0;
|
margin: 8 0 0;
|
||||||
border-radius: 4;
|
border-radius: 4;
|
||||||
border-color: $gray6;
|
border-color: $gray6;
|
||||||
placeholder-color: $gray6;
|
placeholder-color: $gray6;
|
||||||
|
@ -184,8 +177,11 @@ TimePickerField {
|
||||||
TextView {
|
TextView {
|
||||||
line-height: 12;
|
line-height: 12;
|
||||||
}
|
}
|
||||||
|
ListPicker {
|
||||||
|
width: 25%;
|
||||||
|
}
|
||||||
SearchBar {
|
SearchBar {
|
||||||
font-family: "Orkney-Regular";
|
font-family: 'Orkney-Regular';
|
||||||
font-size: 16;
|
font-size: 16;
|
||||||
text-field-hint-color: $gray6;
|
text-field-hint-color: $gray6;
|
||||||
}
|
}
|
||||||
|
@ -203,16 +199,15 @@ TabView {
|
||||||
.progressContainer {
|
.progressContainer {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
.text-btn,
|
|
||||||
.group-header,
|
|
||||||
.category,
|
.category,
|
||||||
|
.group-header,
|
||||||
|
.text-btn,
|
||||||
MDActivityIndicator {
|
MDActivityIndicator {
|
||||||
color: $orange;
|
color: $orange;
|
||||||
}
|
}
|
||||||
MDProgress {
|
MDProgress {
|
||||||
progress-color: $orange;
|
progress-color: $orange;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------
|
// -----------------------------
|
||||||
// ActionBar
|
// ActionBar
|
||||||
ActionBar {
|
ActionBar {
|
||||||
|
@ -260,17 +255,20 @@ ActionBar {
|
||||||
padding: 2 16 0 0;
|
padding: 2 16 0 0;
|
||||||
font-size: 16;
|
font-size: 16;
|
||||||
vertical-alignment: center;
|
vertical-alignment: center;
|
||||||
&.bx{
|
&.bx {
|
||||||
padding: 0 0 0 16;
|
padding: 0 0 0 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MDRipple {
|
MDRipple {
|
||||||
padding: 0 16;
|
padding: 0 16;
|
||||||
}
|
}
|
||||||
|
MDButton.bx {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.sd-group-header {
|
.sd-group-header {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 8;
|
padding: 0 0 8 8;
|
||||||
}
|
}
|
||||||
MDRipple {
|
MDRipple {
|
||||||
border-radius: 4;
|
border-radius: 4;
|
||||||
|
@ -313,7 +311,7 @@ MDButton {
|
||||||
font-size: 20;
|
font-size: 20;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0 0 8;
|
||||||
horizontal-alignment: center;
|
horizontal-alignment: center;
|
||||||
.bx {
|
.bx {
|
||||||
font-size: 24;
|
font-size: 24;
|
||||||
|
@ -404,8 +402,8 @@ RadListView {
|
||||||
// VIEW RECIPE
|
// VIEW RECIPE
|
||||||
.viewRecipe {
|
.viewRecipe {
|
||||||
.category,
|
.category,
|
||||||
.time,
|
.ingredient,
|
||||||
.ingredient {
|
.time {
|
||||||
font-size: 16;
|
font-size: 16;
|
||||||
}
|
}
|
||||||
.category {
|
.category {
|
||||||
|
@ -413,14 +411,15 @@ RadListView {
|
||||||
}
|
}
|
||||||
.time {
|
.time {
|
||||||
margin: 0 8;
|
margin: 0 8;
|
||||||
.bx {
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.title {
|
.title {
|
||||||
font-size: 22;
|
font-size: 22;
|
||||||
line-height: 6;
|
line-height: 6;
|
||||||
}
|
}
|
||||||
|
.subTitle {
|
||||||
|
font-size: 18;
|
||||||
|
line-height: 4;
|
||||||
|
}
|
||||||
.overviewContainer {
|
.overviewContainer {
|
||||||
margin-top: 12;
|
margin-top: 12;
|
||||||
.overviewItem {
|
.overviewItem {
|
||||||
|
@ -507,7 +506,7 @@ MDFloatingActionButton {
|
||||||
font-size: 14;
|
font-size: 14;
|
||||||
horizontal-alignment: left;
|
horizontal-alignment: left;
|
||||||
padding: 12;
|
padding: 12;
|
||||||
margin: 8 0 0 0;
|
margin: 8 0 0;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
MDButton.closeBtn {
|
MDButton.closeBtn {
|
||||||
|
@ -544,7 +543,7 @@ MDButton.closeBtn {
|
||||||
padding: 0 0 0 16;
|
padding: 0 0 0 16;
|
||||||
}
|
}
|
||||||
.recipes {
|
.recipes {
|
||||||
margin: 4 8 4;
|
margin: 4 8;
|
||||||
.recipeTitle {
|
.recipeTitle {
|
||||||
font-size: 14;
|
font-size: 14;
|
||||||
padding: 6 8;
|
padding: 6 8;
|
||||||
|
@ -555,8 +554,8 @@ MDButton.closeBtn {
|
||||||
vertical-alignment: top;
|
vertical-alignment: top;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MDRipple,
|
MDButton,
|
||||||
MDButton {
|
MDRipple {
|
||||||
ripple-color: rgba($gray6, 0.2);
|
ripple-color: rgba($gray6, 0.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -612,7 +611,6 @@ MDButton.closeBtn {
|
||||||
margin: 0 16 16;
|
margin: 0 16 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------
|
// -----------------------------
|
||||||
MDActivityIndicator {
|
MDActivityIndicator {
|
||||||
width: 24;
|
width: 24;
|
||||||
|
@ -647,7 +645,6 @@ MDActivityIndicator {
|
||||||
75% {
|
75% {
|
||||||
transform: scale(1.1);
|
transform: scale(1.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
}
|
}
|
||||||
|
@ -656,7 +653,6 @@ MDActivityIndicator {
|
||||||
0% {
|
0% {
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
transform: scale(0);
|
transform: scale(0);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
|
@ -1,95 +1,71 @@
|
||||||
<template>
|
<template>
|
||||||
<Page @loaded="onPageLoad">
|
<Page @loaded="onPageLoad">
|
||||||
<ActionBar :androidElevation="viewIsScrolled ? 4 : 0">
|
<ActionBar :androidElevation="viewIsScrolled ? 4 : 0">
|
||||||
<GridLayout rows="*" columns="auto, *">
|
<GridLayout rows="*" columns="auto, *">
|
||||||
<MDButton
|
<MDButton variant="text" class="bx" :text="icon.menu" automationText="Back" @tap="showDrawer" col="0" />
|
||||||
variant="text"
|
<Label class="title orkm" :text="'About' | L" col="1" />
|
||||||
class="bx"
|
|
||||||
:text="icon.menu"
|
|
||||||
automationText="Back"
|
|
||||||
@tap="showDrawer"
|
|
||||||
col="0"
|
|
||||||
/>
|
|
||||||
<Label class="title orkm" text="About" col="1" />
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</ActionBar>
|
</ActionBar>
|
||||||
<ScrollView @scroll="onScroll">
|
<ScrollView @scroll="onScroll">
|
||||||
<StackLayout class="main-container">
|
<StackLayout class="main-container">
|
||||||
<StackLayout
|
<StackLayout horizontalAlignment="center" orientation="horizontal" class="appIconContainer">
|
||||||
horizontalAlignment="center"
|
|
||||||
orientation="horizontal"
|
|
||||||
class="appIconContainer"
|
|
||||||
>
|
|
||||||
<Image src="res://logo" class="appIcon" stretch="aspectFit" />
|
<Image src="res://logo" class="appIcon" stretch="aspectFit" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<StackLayout class="m-8"></StackLayout>
|
<StackLayout class="m-8"></StackLayout>
|
||||||
<GridLayout columns="auto, *" class="option">
|
<GridLayout columns="auto, *" class="option">
|
||||||
<Label col="0" class="bx" :text="icon.info" />
|
<Label col="0" class="bx" :text="icon.info" />
|
||||||
<StackLayout col="1">
|
<StackLayout col="1">
|
||||||
<Label text="Version" />
|
<Label :text="'Version' | L" />
|
||||||
<Label :text="getVersion" class="info" textWrap="true" />
|
<Label :text="getVersion" class="info" textWrap="true" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<GridLayout columns="auto, *" class="option">
|
<GridLayout columns="auto, *" class="option">
|
||||||
<MDRipple
|
<MDRipple colSpan="2" @tap="openURL('https://github.com/vishnuraghavb/enrecipes')" />
|
||||||
colSpan="2"
|
|
||||||
@tap="openURL('https://github.com/vishnuraghavb/enrecipes')"
|
|
||||||
/>
|
|
||||||
<Label col="0" class="bx" :text="icon.link" />
|
<Label col="0" class="bx" :text="icon.link" />
|
||||||
<Label
|
<Label verticalAlignment="center" col="1" :text="'View project on GitHub' | L" textWrap="true" />
|
||||||
verticalAlignment="center"
|
|
||||||
col="1"
|
|
||||||
text="View project on GitHub"
|
|
||||||
/>
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<GridLayout columns="auto, *" class="option">
|
<GridLayout columns="auto, *" class="option">
|
||||||
<MDRipple colSpan="2" @tap="openURL('https://t.me/enrecipes')" />
|
<MDRipple colSpan="2" @tap="openURL('https://t.me/enrecipes')" />
|
||||||
<Label col="0" class="bx" :text="icon.telegram" />
|
<Label col="0" class="bx" :text="icon.telegram" />
|
||||||
<StackLayout col="1">
|
<StackLayout col="1">
|
||||||
<Label text="Join the Telegram group" />
|
<Label :text="'Join the Telegram group' | L" textWrap="true" />
|
||||||
<Label
|
<Label :text="'for reporting issues, suggestions and feedback' | L" class="info" textWrap="true" />
|
||||||
text="for reporting issues, suggestions and feedback"
|
|
||||||
class="info"
|
|
||||||
textWrap="true"
|
|
||||||
/>
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
|
|
||||||
<StackLayout class="hr m-10"></StackLayout>
|
<StackLayout class="hr m-10"></StackLayout>
|
||||||
|
|
||||||
<Label text="Author" class="group-header orkm" />
|
<Label :text="'Author' | L" class="group-header orkm" />
|
||||||
<GridLayout columns="auto, *" class="option">
|
<GridLayout columns="auto, *" class="option">
|
||||||
<MDRipple
|
<MDRipple colSpan="2" @tap="openURL('https://www.vishnuraghav.com')" />
|
||||||
colSpan="2"
|
|
||||||
@tap="openURL('https://www.vishnuraghav.com')"
|
|
||||||
/>
|
|
||||||
<Label col="0" class="bx" :text="icon.user" />
|
<Label col="0" class="bx" :text="icon.user" />
|
||||||
<Label verticalAlignment="center" col="1" text="Vishnu Raghav B" />
|
<Label verticalAlignment="center" col="1" :text="'Vishnu Raghav B' | L" textWrap="true" />
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<GridLayout columns="auto, *" class="option">
|
<GridLayout columns="auto, *" class="option">
|
||||||
<MDRipple
|
<MDRipple colSpan="2" @tap="openURL('https://github.com/vishnuraghavb')" />
|
||||||
colSpan="2"
|
|
||||||
@tap="openURL('https://github.com/vishnuraghavb')"
|
|
||||||
/>
|
|
||||||
<Label col="0" class="bx" :text="icon.link" />
|
<Label col="0" class="bx" :text="icon.link" />
|
||||||
<Label verticalAlignment="center" col="1" text="Follow on GitHub" />
|
<Label verticalAlignment="center" col="1" :text="'Follow on GitHub' | L" textWrap="true" />
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<GridLayout columns="auto, *" class="option">
|
<GridLayout columns="auto, *" class="option">
|
||||||
<MDRipple
|
<MDRipple colSpan="2" @tap="openURL('https://mastodon.social/@vishnuraghavb')" />
|
||||||
colSpan="2"
|
|
||||||
@tap="openURL('https://mastodon.social/@vishnuraghavb')"
|
|
||||||
/>
|
|
||||||
<Label col="0" class="bx" :text="icon.link" />
|
<Label col="0" class="bx" :text="icon.link" />
|
||||||
<Label verticalAlignment="center" col="1" text="Follow on Mastodon" />
|
<Label verticalAlignment="center" col="1" :text="'Follow on Mastodon' | L" textWrap="true" />
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { Application, Utils } from "@nativescript/core"
|
import {
|
||||||
import { mapActions, mapState } from "vuex"
|
Application,
|
||||||
|
Utils,
|
||||||
|
Observable
|
||||||
|
} from "@nativescript/core"
|
||||||
|
import {
|
||||||
|
mapActions,
|
||||||
|
mapState
|
||||||
|
} from "vuex"
|
||||||
|
|
||||||
import * as utils from "~/shared/utils"
|
import * as utils from "~/shared/utils"
|
||||||
|
|
||||||
|
@ -110,7 +86,9 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions(["setCurrentComponentAction"]),
|
...mapActions(["setCurrentComponentAction"]),
|
||||||
onPageLoad() {
|
onPageLoad(args) {
|
||||||
|
const page = args.object;
|
||||||
|
page.bindingContext = new Observable();
|
||||||
this.setCurrentComponentAction("About")
|
this.setCurrentComponentAction("About")
|
||||||
},
|
},
|
||||||
// HELPERS
|
// HELPERS
|
||||||
|
|
|
@ -1,141 +1,60 @@
|
||||||
<template>
|
<template>
|
||||||
<Page
|
<Page @loaded="onPageLoad" actionBarHidden="true" :androidStatusBarBackground="appTheme == 'Light' ? '#f1f3f5' : '#212529'">
|
||||||
@loaded="onPageLoad"
|
|
||||||
actionBarHidden="true"
|
<RadSideDrawer allowEdgeSwipe="true" showOverNavigation="true" ref="drawer" id="sideDrawer" drawerContentSize="270" gesturesEnabled="true" drawerTransition="SlideInOnTopTransition">
|
||||||
:androidStatusBarBackground="appTheme == 'Light' ? '#f1f3f5' : '#212529'"
|
|
||||||
>
|
|
||||||
<RadSideDrawer
|
|
||||||
allowEdgeSwipe="true"
|
|
||||||
showOverNavigation="true"
|
|
||||||
ref="drawer"
|
|
||||||
id="sideDrawer"
|
|
||||||
drawerContentSize="270"
|
|
||||||
gesturesEnabled="true"
|
|
||||||
drawerTransition="SlideInOnTopTransition"
|
|
||||||
>
|
|
||||||
<GridLayout rows="*, auto" columns="*" ~drawerContent class="sd">
|
<GridLayout rows="*, auto" columns="*" ~drawerContent class="sd">
|
||||||
<StackLayout row="0">
|
<StackLayout row="0">
|
||||||
<GridLayout
|
<GridLayout rows="48" columns="auto, 24, *" v-for="(item, index) in topmenu" :key="index" class="sd-item orkm" :class="{
|
||||||
rows="48"
|
|
||||||
columns="auto, 24, *"
|
|
||||||
v-for="(item, index) in topmenu"
|
|
||||||
:key="index"
|
|
||||||
class="sd-item orkm"
|
|
||||||
:class="{
|
|
||||||
'selected-sd-item': currentComponent === item.component,
|
'selected-sd-item': currentComponent === item.component,
|
||||||
}"
|
}">
|
||||||
>
|
<MDRipple row="0" colSpan="3" @tap="navigateTo(item.component, item.component, false, false)" />
|
||||||
<MDRipple
|
|
||||||
row="0"
|
|
||||||
colSpan="3"
|
|
||||||
@tap="navigateTo(item.component, false, false)"
|
|
||||||
/>
|
|
||||||
<Label col="0" row="0" class="bx" :text="icon[item.icon]" />
|
<Label col="0" row="0" class="bx" :text="icon[item.icon]" />
|
||||||
<Label col="2" row="0" :text="item.title" />
|
<Label col="2" row="0" :text="`${item.title}` | L" />
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<StackLayout class="hr m-8"></StackLayout>
|
<StackLayout class="hr" margin="8"></StackLayout>
|
||||||
<GridLayout
|
<GridLayout rows="48" columns="auto, 24, *" class="sd-item orkm" :class="{
|
||||||
rows="48"
|
|
||||||
columns="auto, 24, *"
|
|
||||||
class="sd-item orkm"
|
|
||||||
:class="{
|
|
||||||
'selected-sd-item': currentComponent === 'MealPlanner',
|
'selected-sd-item': currentComponent === 'MealPlanner',
|
||||||
}"
|
}">
|
||||||
>
|
<MDRipple row="0" colSpan="3" @tap="navigateTo(MealPlanner, 'MealPlanner', true, false)" />
|
||||||
<MDRipple
|
|
||||||
row="0"
|
|
||||||
colSpan="3"
|
|
||||||
@tap="navigateTo(MealPlanner, true, false)"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Label col="0" row="0" class="bx" :text="icon.calendar" />
|
<Label col="0" row="0" class="bx" :text="icon.calendar" />
|
||||||
<Label col="2" row="0" text="Meal Planner" />
|
<Label col="2" row="0" :text="'Meal Planner' | L" />
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<StackLayout class="hr m-8"></StackLayout>
|
<StackLayout class="hr" margin="8"></StackLayout>
|
||||||
<GridLayout
|
<GridLayout class="sd-group-header orkm" rows="auto" columns="*, auto" v-if="categoriesWithRecipes.length">
|
||||||
class="sd-group-header orkm"
|
<Label verticalAlignment="center" col="0" :text="'Categories' | L" />
|
||||||
rows="auto"
|
<MDButton variant="text" @tap="toggleCatEdit" col="2" :text="`${editCategory ? 'DONE' : 'RENAME'}` | L" />
|
||||||
columns="*, auto"
|
|
||||||
v-if="categoriesWithRecipes.length"
|
|
||||||
>
|
|
||||||
<Label verticalAlignment="center" col="0" text="Categories" />
|
|
||||||
<MDButton
|
|
||||||
variant="text"
|
|
||||||
@tap="toggleCatEdit"
|
|
||||||
col="2"
|
|
||||||
:text="editCategory ? 'DONE' : 'RENAME'"
|
|
||||||
/>
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<ScrollView height="100%">
|
<ScrollView height="100%">
|
||||||
<StackLayout>
|
<StackLayout>
|
||||||
<GridLayout
|
<GridLayout v-for="(item, index) in categoriesWithRecipes" :key="index" class="sd-item orkm" :class="{
|
||||||
v-for="(item, index) in categoriesWithRecipes"
|
|
||||||
:key="index"
|
|
||||||
class="sd-item orkm"
|
|
||||||
:class="{
|
|
||||||
'selected-sd-item': currentComponent == item,
|
'selected-sd-item': currentComponent == item,
|
||||||
}"
|
}" columns="auto, *, auto">
|
||||||
columns="auto, *, auto"
|
<MDRipple row="0" colSpan="3" @tap="navigateTo(item, item, false, true)" />
|
||||||
>
|
<Label col="0" class="bx" :text="icon.label" margin="0 24 0 0" />
|
||||||
<MDRipple
|
<Label col="1" :text="`${item}` | L" />
|
||||||
row="0"
|
<MDButton variant="text" v-if="editCategory" @tap="renameCategory(item)" col="2" class="bx" :text="icon.edit" />
|
||||||
colSpan="3"
|
|
||||||
@tap="navigateTo(item, false, true)"
|
|
||||||
/>
|
|
||||||
<Label
|
|
||||||
col="0"
|
|
||||||
class="bx"
|
|
||||||
:text="icon.label"
|
|
||||||
margin="0 24 0 0"
|
|
||||||
/>
|
|
||||||
<Label col="1" :text="item" />
|
|
||||||
<MDButton
|
|
||||||
variant="text"
|
|
||||||
v-if="editCategory"
|
|
||||||
@tap="renameCategory(item)"
|
|
||||||
col="2"
|
|
||||||
class="bx"
|
|
||||||
:text="icon.edit"
|
|
||||||
/>
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<StackLayout row="1">
|
<StackLayout row="1">
|
||||||
<StackLayout class="hr m-10"></StackLayout>
|
<StackLayout class="hr" margin="0 8 8"></StackLayout>
|
||||||
<GridLayout
|
<GridLayout class="sd-item orkm" :class="{
|
||||||
class="sd-item orkm"
|
|
||||||
:class="{
|
|
||||||
'selected-sd-item': currentComponent == item.title,
|
'selected-sd-item': currentComponent == item.title,
|
||||||
}"
|
}" v-for="(item, index) in bottommenu" :key="index" rows="48" columns="auto, 24, *">
|
||||||
v-for="(item, index) in bottommenu"
|
<MDRipple colSpan="3" @tap="navigateTo(item.component, 'item.title', true, false)" />
|
||||||
:key="index"
|
|
||||||
rows="48"
|
|
||||||
columns="auto, 24, *"
|
|
||||||
>
|
|
||||||
<MDRipple
|
|
||||||
colSpan="3"
|
|
||||||
@tap="navigateTo(item.component, true, false)"
|
|
||||||
/>
|
|
||||||
<Label class="bx" col="0" :text="icon[item.icon]" />
|
<Label class="bx" col="0" :text="icon[item.icon]" />
|
||||||
<Label col="2" :text="item.title" />
|
<Label col="2" :text="`${item.title}` | L" />
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<Frame ~mainContent id="main-frame">
|
<Frame ~mainContent id="main-frame">
|
||||||
<!-- Home -->
|
<EnRecipes ref="enrecipes" :filterFavourites="filterFavourites" :filterTrylater="filterTrylater" :selectedCategory="selectedCategory" :closeDrawer="closeDrawer" :hijackGlobalBackEvent="hijackGlobalBackEvent"
|
||||||
<EnRecipes
|
:releaseGlobalBackEvent="releaseGlobalBackEvent" />
|
||||||
ref="enrecipes"
|
|
||||||
:filterFavorites="filterFavorites"
|
|
||||||
:filterTrylater="filterTrylater"
|
|
||||||
:selectedCategory="selectedCategory"
|
|
||||||
:closeDrawer="closeDrawer"
|
|
||||||
:hijackGlobalBackEvent="hijackGlobalBackEvent"
|
|
||||||
:releaseGlobalBackEvent="releaseGlobalBackEvent"
|
|
||||||
/>
|
|
||||||
</Frame>
|
</Frame>
|
||||||
</RadSideDrawer>
|
</RadSideDrawer>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -143,11 +62,17 @@ import {
|
||||||
ApplicationSettings,
|
ApplicationSettings,
|
||||||
AndroidApplication,
|
AndroidApplication,
|
||||||
Application,
|
Application,
|
||||||
} from "@nativescript/core"
|
Device
|
||||||
|
}
|
||||||
|
from "@nativescript/core"
|
||||||
import Theme from "@nativescript/theme"
|
import Theme from "@nativescript/theme"
|
||||||
import * as Toast from "nativescript-toast"
|
import * as Toast from "nativescript-toast"
|
||||||
import * as application from "tns-core-modules/application"
|
import * as application from "tns-core-modules/application"
|
||||||
import { mapActions, mapState } from "vuex"
|
import {
|
||||||
|
mapActions,
|
||||||
|
mapState
|
||||||
|
}
|
||||||
|
from "vuex"
|
||||||
|
|
||||||
import EnRecipes from "./EnRecipes"
|
import EnRecipes from "./EnRecipes"
|
||||||
import MealPlanner from "./MealPlanner"
|
import MealPlanner from "./MealPlanner"
|
||||||
|
@ -160,11 +85,10 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
selectedCategory: null,
|
selectedCategory: null,
|
||||||
filterFavorites: false,
|
filterFavourites: false,
|
||||||
filterTrylater: false,
|
filterTrylater: false,
|
||||||
MealPlanner: MealPlanner,
|
MealPlanner: MealPlanner,
|
||||||
topmenu: [
|
topmenu: [ {
|
||||||
{
|
|
||||||
title: "EnRecipes",
|
title: "EnRecipes",
|
||||||
component: "EnRecipes",
|
component: "EnRecipes",
|
||||||
icon: "home",
|
icon: "home",
|
||||||
|
@ -175,13 +99,12 @@ export default {
|
||||||
icon: "trylater",
|
icon: "trylater",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Favorites",
|
title: "Favourites",
|
||||||
component: "Favorites",
|
component: "Favourites",
|
||||||
icon: "heart",
|
icon: "heart",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
bottommenu: [
|
bottommenu: [ {
|
||||||
{
|
|
||||||
title: "Settings",
|
title: "Settings",
|
||||||
component: Settings,
|
component: Settings,
|
||||||
icon: "cog",
|
icon: "cog",
|
||||||
|
@ -201,68 +124,68 @@ export default {
|
||||||
MealPlanner,
|
MealPlanner,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState([
|
...mapState( [
|
||||||
"icon",
|
"icon",
|
||||||
"recipes",
|
"recipes",
|
||||||
"categories",
|
"categories",
|
||||||
"yieldUnits",
|
"yieldUnits",
|
||||||
"mealPlans",
|
"mealPlans",
|
||||||
"currentComponent",
|
"currentComponent",
|
||||||
]),
|
] ),
|
||||||
categoriesWithRecipes() {
|
categoriesWithRecipes() {
|
||||||
let arr = this.recipes.map((e) => {
|
let arr = this.recipes.map( ( e ) => {
|
||||||
return e.category
|
return e.category
|
||||||
})
|
} )
|
||||||
return [...new Set(arr)]
|
return [ ...new Set( arr ) ]
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions([
|
...mapActions( [
|
||||||
"setCurrentComponentAction",
|
"setCurrentComponentAction",
|
||||||
"initializeRecipes",
|
"initializeRecipes",
|
||||||
"initializeCategories",
|
"initializeCategories",
|
||||||
"initializeYieldUnits",
|
"initializeYieldUnits",
|
||||||
"initializeMealPlans",
|
"initializeMealPlans",
|
||||||
"renameCategoryAction",
|
"renameCategoryAction",
|
||||||
]),
|
] ),
|
||||||
onPageLoad() {
|
onPageLoad() {
|
||||||
if (this.appTheme === "Light") {
|
if ( this.appTheme === "Light" ) {
|
||||||
const View = android.view.View
|
const View = android.view.View
|
||||||
const window = Application.android.startActivity.getWindow()
|
const window = Application.android.startActivity.getWindow()
|
||||||
const decorView = window.getDecorView()
|
const decorView = window.getDecorView()
|
||||||
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR)
|
decorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR )
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// HELPERS
|
// HELPERS
|
||||||
toggleCatEdit() {
|
toggleCatEdit() {
|
||||||
this.editCategory = !this.editCategory
|
this.editCategory = !this.editCategory
|
||||||
if (this.selectedCategory) this.setComponent("EnRecipes")
|
if ( this.selectedCategory ) this.setCurrentComponentAction( "EnRecipes" )
|
||||||
this.filterFavorites = this.filterTrylater = false
|
this.filterFavourites = this.filterTrylater = false
|
||||||
this.selectedCategory = null
|
this.selectedCategory = null
|
||||||
this.$refs.enrecipes.updateFilter()
|
this.$refs.enrecipes.updateFilter()
|
||||||
},
|
},
|
||||||
setComponent(comp) {
|
renameCategory( category ) {
|
||||||
this.setCurrentComponentAction(comp)
|
|
||||||
},
|
|
||||||
renameCategory(category) {
|
|
||||||
this.releaseGlobalBackEvent()
|
this.releaseGlobalBackEvent()
|
||||||
this.$showModal(PromptDialog, {
|
this.$showModal( PromptDialog, {
|
||||||
props: {
|
props: {
|
||||||
title: `Rename category`,
|
title: `Rename category`,
|
||||||
text: category,
|
text: category,
|
||||||
action: "RENAME",
|
action: "RENAME",
|
||||||
},
|
},
|
||||||
}).then((newCategory) => {
|
} ).then( ( newCategory ) => {
|
||||||
this.hijackGlobalBackEvent()
|
this.hijackGlobalBackEvent()
|
||||||
if (newCategory.length) {
|
if ( newCategory.length ) {
|
||||||
this.renameCategoryAction({ current: category, updated: newCategory })
|
this.renameCategoryAction( {
|
||||||
|
current: category,
|
||||||
|
updated: newCategory
|
||||||
|
} )
|
||||||
this.editCategory = false
|
this.editCategory = false
|
||||||
this.navigateTo(newCategory, false, true)
|
this.navigateTo( newCategory, newCategory, false, true )
|
||||||
}
|
}
|
||||||
})
|
} )
|
||||||
},
|
},
|
||||||
setSelectedCategory(e) {
|
setSelectedCategory( e ) {
|
||||||
this.selectedCategory = e.item
|
this.selectedCategory = e.item
|
||||||
this.closeDrawer()
|
this.closeDrawer()
|
||||||
},
|
},
|
||||||
|
@ -284,67 +207,68 @@ export default {
|
||||||
this.globalBackEvent
|
this.globalBackEvent
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
globalBackEvent(args) {
|
globalBackEvent( args ) {
|
||||||
function preventDefault() {
|
function preventDefault() {
|
||||||
args.cancel = true
|
args.cancel = true
|
||||||
}
|
}
|
||||||
let vm = this
|
if ( this.$refs.drawer && this.$refs.drawer.nativeView.getIsOpen() ) {
|
||||||
function isFiltered() {
|
|
||||||
vm.filterFavorites
|
|
||||||
? vm.setComponent("Favorites")
|
|
||||||
: vm.filterTrylater
|
|
||||||
? vm.setComponent("Try Later")
|
|
||||||
: vm.selectedCategory
|
|
||||||
? vm.setComponent(vm.selectedCategory)
|
|
||||||
: vm.setComponent("EnRecipes")
|
|
||||||
}
|
|
||||||
if (this.$refs.drawer && this.$refs.drawer.nativeView.getIsOpen()) {
|
|
||||||
preventDefault()
|
preventDefault()
|
||||||
this.closeDrawer()
|
this.closeDrawer()
|
||||||
this.editCategory = false
|
this.editCategory = false
|
||||||
} else if (
|
}
|
||||||
["Favorites", "Try Later", this.selectedCategory].includes(
|
else if (
|
||||||
|
[ "Favourites", "Try Later", this.selectedCategory ].includes(
|
||||||
this.currentComponent
|
this.currentComponent
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
preventDefault()
|
preventDefault()
|
||||||
this.setComponent("EnRecipes")
|
this.setCurrentComponentAction( "EnRecipes" )
|
||||||
this.filterFavorites = this.filterTrylater = false
|
this.filterFavourites = this.filterTrylater = false
|
||||||
this.selectedCategory = null
|
this.selectedCategory = null
|
||||||
this.$refs.enrecipes.updateFilter()
|
this.$refs.enrecipes.updateFilter()
|
||||||
this.releaseGlobalBackEvent()
|
this.releaseGlobalBackEvent()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
navigateTo(to, isTrueComponent, isCategory) {
|
navigateTo( to, title, isTrueComponent, isCategory ) {
|
||||||
if (isTrueComponent) {
|
if ( title !== this.currentComponent ) {
|
||||||
this.$navigateTo(to, {
|
if ( isTrueComponent ) {
|
||||||
|
this.$navigateTo( to, {
|
||||||
frame: "main-frame",
|
frame: "main-frame",
|
||||||
backstackVisible: false,
|
backstackVisible: false
|
||||||
})
|
} )
|
||||||
this.closeDrawer()
|
this.closeDrawer()
|
||||||
} else if (!this.editCategory || !isCategory) {
|
}
|
||||||
|
else if ( !this.editCategory || !isCategory ) {
|
||||||
this.releaseGlobalBackEvent()
|
this.releaseGlobalBackEvent()
|
||||||
this.hijackGlobalBackEvent()
|
this.hijackGlobalBackEvent()
|
||||||
this.setComponent(to)
|
this.setCurrentComponentAction( to )
|
||||||
this.$navigateBack({ frame: "main-frame", backstackVisible: false })
|
this.$navigateBack( {
|
||||||
this.filterFavorites = to === "Favorites" ? true : false
|
frame: "main-frame",
|
||||||
|
backstackVisible: false
|
||||||
|
} )
|
||||||
|
this.filterFavourites = to === "Favourites" ? true : false
|
||||||
this.filterTrylater = to === "Try Later" ? true : false
|
this.filterTrylater = to === "Try Later" ? true : false
|
||||||
this.selectedCategory = isCategory ? to : null
|
this.selectedCategory = isCategory ? to : null
|
||||||
this.$refs.enrecipes.updateFilter()
|
this.$refs.enrecipes.updateFilter()
|
||||||
this.closeDrawer()
|
this.closeDrawer()
|
||||||
}
|
}
|
||||||
this.editCategory = false
|
this.editCategory = false
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.closeDrawer()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.appTheme = ApplicationSettings.getString("appTheme", "Light")
|
this.appTheme = ApplicationSettings.getString( "appTheme", "Light" )
|
||||||
setTimeout((e) => {
|
setTimeout( ( e ) => {
|
||||||
Theme.setMode(Theme[this.appTheme])
|
Theme.setMode( Theme[ this.appTheme ] )
|
||||||
}, 10)
|
}, 10 )
|
||||||
if (!this.recipes.length) this.initializeRecipes()
|
if ( !this.recipes.length ) this.initializeRecipes()
|
||||||
if (!this.categories.length) this.initializeCategories()
|
if ( !this.categories.length ) this.initializeCategories()
|
||||||
if (!this.yieldUnits.length) this.initializeYieldUnits()
|
if ( !this.yieldUnits.length ) this.initializeYieldUnits()
|
||||||
if (!this.mealPlans.length) this.initializeMealPlans()
|
if ( !this.mealPlans.length ) this.initializeMealPlans()
|
||||||
|
console.log( Device.language );
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,111 +1,37 @@
|
||||||
<template>
|
<template>
|
||||||
<Page @loaded="onPageLoad">
|
<Page @loaded="onPageLoad" @unloaded="onPageUnload">
|
||||||
<ActionBar :androidElevation="viewIsScrolled ? 4 : 0">
|
<ActionBar :androidElevation="viewIsScrolled ? 4 : 0">
|
||||||
<!-- Search Actionbar -->
|
<GridLayout v-if="showSearch" columns="auto, *" verticalAlignment="center">
|
||||||
<GridLayout
|
<MDButton class="bx" :text="icon.back" variant="text" automationText="Back" col="0" @tap="closeSearch" />
|
||||||
v-if="showSearch"
|
<SearchBar col="1" :hint="'Search' | L" v-model="searchQuery" @textChange="updateFilter" @clear="clearSearch" />
|
||||||
columns="auto, *"
|
|
||||||
verticalAlignment="center"
|
|
||||||
>
|
|
||||||
<MDButton
|
|
||||||
class="bx"
|
|
||||||
:text="icon.back"
|
|
||||||
variant="text"
|
|
||||||
automationText="Back"
|
|
||||||
col="0"
|
|
||||||
@tap="closeSearch"
|
|
||||||
/>
|
|
||||||
<SearchBar
|
|
||||||
col="1"
|
|
||||||
hint="Search"
|
|
||||||
v-model="searchQuery"
|
|
||||||
@textChange="updateFilter"
|
|
||||||
@clear="clearSearch"
|
|
||||||
/>
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<!-- Home Actionbar -->
|
|
||||||
<GridLayout v-else columns="auto, *, auto, auto">
|
<GridLayout v-else columns="auto, *, auto, auto">
|
||||||
<MDButton
|
<MDButton class="bx" col="0" variant="text" @tap="showDrawer" :text="icon.menu" automationText="Back" />
|
||||||
class="bx"
|
<Label class="title orkm" :text="`${currentComponent}` | L" col="1" />
|
||||||
col="0"
|
<MDButton v-if="recipes.length" class="bx" :text="icon.search" variant="text" col="2" @tap="openSearch" />
|
||||||
variant="text"
|
<MDButton v-if="recipes.length" class="bx" :text="icon.sort" variant="text" col="3" @tap="sortDialog" />
|
||||||
@tap="showDrawer"
|
|
||||||
:text="icon.menu"
|
|
||||||
automationText="Back"
|
|
||||||
/>
|
|
||||||
<Label class="title orkm" :text="currentComponent" col="1" />
|
|
||||||
<MDButton
|
|
||||||
v-if="recipes.length"
|
|
||||||
class="bx"
|
|
||||||
:text="icon.search"
|
|
||||||
variant="text"
|
|
||||||
col="2"
|
|
||||||
@tap="openSearch"
|
|
||||||
/>
|
|
||||||
<MDButton
|
|
||||||
v-if="recipes.length"
|
|
||||||
class="bx"
|
|
||||||
:text="icon.sort"
|
|
||||||
variant="text"
|
|
||||||
col="3"
|
|
||||||
@tap="sortDialog"
|
|
||||||
/>
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</ActionBar>
|
</ActionBar>
|
||||||
<AbsoluteLayout>
|
<AbsoluteLayout>
|
||||||
<RadListView
|
<RadListView ref="listView" itemHeight="112" for="recipe in recipes" swipeActions="true" @itemSwipeProgressChanged="onSwiping" @itemSwipeProgressEnded="onSwipeEnded" @scrolled="onScroll" :filteringFunction="filterFunction"
|
||||||
ref="listView"
|
:sortingFunction="sortFunction">
|
||||||
itemHeight="112"
|
|
||||||
for="recipe in recipes"
|
|
||||||
swipeActions="true"
|
|
||||||
@itemSwipeProgressChanged="onSwiping"
|
|
||||||
@itemSwipeProgressEnded="onSwipeEnded"
|
|
||||||
@scrolled="onScroll"
|
|
||||||
:filteringFunction="filterFunction"
|
|
||||||
:sortingFunction="sortFunction"
|
|
||||||
>
|
|
||||||
<v-template>
|
<v-template>
|
||||||
<GridLayout
|
<GridLayout class="recipeItem" rows="112" columns="112, *" androidElevation="1">
|
||||||
class="recipeItem"
|
|
||||||
rows="112"
|
|
||||||
columns="112, *"
|
|
||||||
androidElevation="1"
|
|
||||||
>
|
|
||||||
<MDRipple colSpan="2" @tap="viewRecipe(recipe.id)" />
|
<MDRipple colSpan="2" @tap="viewRecipe(recipe.id)" />
|
||||||
<GridLayout class="imageHolder card" rows="112" columns="112">
|
<GridLayout class="imageHolder card" rows="112" columns="112">
|
||||||
<Image
|
<Image row="0" col="0" v-if="recipe.imageSrc" :src="recipe.imageSrc" stretch="aspectFill" decodeWidth="112" decodeHeight="112" loadMode="async" />
|
||||||
row="0"
|
<Label v-else row="0" col="0" horizontalAlignment="center" class="bx" fontSize="56" :text="icon.image" />
|
||||||
col="0"
|
|
||||||
v-if="recipe.imageSrc"
|
|
||||||
:src="recipe.imageSrc"
|
|
||||||
stretch="aspectFill"
|
|
||||||
decodeWidth="112"
|
|
||||||
decodeHeight="112"
|
|
||||||
loadMode="async"
|
|
||||||
/>
|
|
||||||
<Label
|
|
||||||
v-else
|
|
||||||
row="0"
|
|
||||||
col="0"
|
|
||||||
horizontalAlignment="center"
|
|
||||||
class="bx"
|
|
||||||
fontSize="56"
|
|
||||||
:text="icon.image"
|
|
||||||
/>
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<StackLayout class="recipeInfo" col="1">
|
<StackLayout class="recipeInfo" col="1">
|
||||||
<Label :text="recipe.category" class="orkm category" />
|
<Label :text="`${recipe.category}` | L" class="orkm category" />
|
||||||
<Label :text="recipe.title" class="orkm title" />
|
<Label :text="recipe.title" class="orkm title" />
|
||||||
<StackLayout class="timeContainer" orientation="horizontal">
|
<StackLayout class="timeContainer" orientation="horizontal">
|
||||||
<Label class="bx small" :text="icon.time" />
|
<Label class="bx small" :text="icon.time" />
|
||||||
<Label
|
<Label class="time" :text="
|
||||||
class="time"
|
|
||||||
:text="
|
|
||||||
`${
|
`${
|
||||||
formattedTotalTime(recipe.prepTime, recipe.cookTime).time
|
formattedTotalTime(recipe.prepTime, recipe.cookTime).time
|
||||||
}`
|
}`
|
||||||
"
|
" />
|
||||||
/>
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
|
@ -122,125 +48,76 @@
|
||||||
</v-template>
|
</v-template>
|
||||||
</RadListView>
|
</RadListView>
|
||||||
<GridLayout rows="*, auto, *, 88" columns="*" class="emptyStateContainer">
|
<GridLayout rows="*, auto, *, 88" columns="*" class="emptyStateContainer">
|
||||||
<StackLayout
|
<StackLayout row="1" class="emptyState" v-if="
|
||||||
row="1"
|
|
||||||
class="emptyState"
|
|
||||||
v-if="
|
|
||||||
!recipes.length &&
|
!recipes.length &&
|
||||||
!filterFavorites &&
|
!filterFavourites &&
|
||||||
!filterTrylater &&
|
!filterTrylater &&
|
||||||
!selectedCategory
|
!selectedCategory
|
||||||
"
|
" @tap="addRecipe">
|
||||||
@tap="addRecipe"
|
|
||||||
>
|
|
||||||
<Label class="bx icon" :text="icon.plusCircle" />
|
<Label class="bx icon" :text="icon.plusCircle" />
|
||||||
<Label
|
<Label class="title orkm" :text="'Start adding your recipes!' | L" textWrap="true" />
|
||||||
class="title orkm"
|
|
||||||
text="Start adding your recipes!"
|
|
||||||
textWrap="true"
|
|
||||||
/>
|
|
||||||
<StackLayout orientation="horizontal" horizontalAlignment="center">
|
<StackLayout orientation="horizontal" horizontalAlignment="center">
|
||||||
<Label text="Use the " />
|
<Label :text="'Use the plus button to add one' | L" textWrap="true" />
|
||||||
<Label class="bx" :text="icon.plus" />
|
|
||||||
<Label text=" button to add one" />
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<StackLayout
|
<StackLayout row="1" class="emptyState" v-if="!filteredRecipes.length && filterTrylater && !searchQuery">
|
||||||
row="1"
|
|
||||||
class="emptyState"
|
|
||||||
v-if="!filteredRecipes.length && filterTrylater && !searchQuery"
|
|
||||||
>
|
|
||||||
<Label class="bx icon" :text="icon.trylaterOutline" textWrap="true" />
|
<Label class="bx icon" :text="icon.trylaterOutline" textWrap="true" />
|
||||||
<Label class="title orkm" text="All done!" textWrap="true" />
|
<Label class="title orkm" :text="'All done!' | L" textWrap="true" />
|
||||||
<Label
|
<Label :text="'Recipes you mark as try later will be listed here' | L" textWrap="true" />
|
||||||
text="Recipes you mark as try later will be listed here"
|
|
||||||
textWrap="true"
|
|
||||||
/>
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<StackLayout
|
<StackLayout row="1" class="emptyState" v-if="!filteredRecipes.length && filterFavourites && !searchQuery">
|
||||||
row="1"
|
|
||||||
class="emptyState"
|
|
||||||
v-if="!filteredRecipes.length && filterFavorites && !searchQuery"
|
|
||||||
>
|
|
||||||
<Label class="bx icon" :text="icon.heartOutline" textWrap="true" />
|
<Label class="bx icon" :text="icon.heartOutline" textWrap="true" />
|
||||||
<Label class="title orkm" text="No favorites yet" textWrap="true" />
|
<Label class="title orkm" :text="'No favourites yet' | L" textWrap="true" />
|
||||||
<Label
|
<Label :text="'Recipes you mark as favourite will be listed here' | L" textWrap="true" />
|
||||||
text="Recipes you mark as favorite will be listed here"
|
|
||||||
textWrap="true"
|
|
||||||
/>
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<StackLayout
|
<StackLayout row="1" class="emptyState" v-if="!filteredRecipes.length && !searchQuery && selectedCategory">
|
||||||
row="1"
|
|
||||||
class="emptyState"
|
|
||||||
v-if="!filteredRecipes.length && !searchQuery && selectedCategory"
|
|
||||||
>
|
|
||||||
<Label class="bx icon" :text="icon.labelOutline" textWrap="true" />
|
<Label class="bx icon" :text="icon.labelOutline" textWrap="true" />
|
||||||
<Label
|
<Label class="title orkm" :text="'Category looks empty' | L" textWrap="true" />
|
||||||
class="title orkm"
|
|
||||||
text="Category looks empty"
|
|
||||||
textWrap="true"
|
|
||||||
/>
|
|
||||||
<StackLayout orientation="horizontal" horizontalAlignment="center">
|
<StackLayout orientation="horizontal" horizontalAlignment="center">
|
||||||
<Label text="Use the " textWrap="true" />
|
<Label :text="'Use the plus button to add one' | L" textWrap="true" />
|
||||||
<Label class="bx" :text="icon.plus" />
|
|
||||||
<Label text=" button to add a recipe" textWrap="true" />
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<StackLayout
|
<StackLayout row="1" class="emptyState" v-if="!filteredRecipes.length && searchQuery">
|
||||||
row="1"
|
|
||||||
class="emptyState"
|
|
||||||
v-if="!filteredRecipes.length && searchQuery"
|
|
||||||
>
|
|
||||||
<Label class="bx icon" :text="icon.search" textWrap="true" />
|
<Label class="bx icon" :text="icon.search" textWrap="true" />
|
||||||
<Label class="title orkm" text="No recipes found" textWrap="true" />
|
<Label class="title orkm" :text="'No recipes found' | L" textWrap="true" />
|
||||||
<Label
|
<Label :text="`${noResultFor}` | L" textWrap="true" />
|
||||||
:text="
|
|
||||||
`Your search "${searchQuery}" did not match any recipes${noResultFor}`
|
|
||||||
"
|
|
||||||
textWrap="true"
|
|
||||||
/>
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<GridLayout id="btnFabContainer" rows="*, auto" columns="*, auto">
|
<GridLayout id="btnFabContainer" rows="*, auto" columns="*, auto">
|
||||||
<transition name="bounce">
|
<transition name="bounce">
|
||||||
<MDFloatingActionButton
|
<MDFloatingActionButton v-if="showFAB" row="1" col="1" class="bx fab-button" src="res://plus" @tap="addRecipe" />
|
||||||
v-if="showFAB"
|
|
||||||
row="1"
|
|
||||||
col="1"
|
|
||||||
class="bx fab-button"
|
|
||||||
src="res://plus"
|
|
||||||
@tap="addRecipe"
|
|
||||||
/>
|
|
||||||
</transition>
|
</transition>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</AbsoluteLayout>
|
</AbsoluteLayout>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { AndroidApplication, Utils } from "@nativescript/core"
|
import {
|
||||||
import { mapActions, mapState } from "vuex"
|
AndroidApplication,
|
||||||
|
Utils,
|
||||||
import EditRecipe from "./EditRecipe.vue"
|
Observable
|
||||||
import ViewRecipe from "./ViewRecipe.vue"
|
}
|
||||||
|
from "@nativescript/core";
|
||||||
import ActionDialog from "./modal/ActionDialog.vue"
|
import {
|
||||||
import ConfirmDialog from "./modal/ConfirmDialog.vue"
|
localize
|
||||||
|
}
|
||||||
import * as utils from "~/shared/utils"
|
from "@nativescript/localize"
|
||||||
|
import {
|
||||||
|
mapActions,
|
||||||
|
mapState
|
||||||
|
}
|
||||||
|
from "vuex";
|
||||||
|
import EditRecipe from "./EditRecipe.vue";
|
||||||
|
import ViewRecipe from "./ViewRecipe.vue";
|
||||||
|
import ActionDialog from "./modal/ActionDialog.vue";
|
||||||
|
import ConfirmDialog from "./modal/ConfirmDialog.vue";
|
||||||
|
import * as utils from "~/shared/utils";
|
||||||
export default {
|
export default {
|
||||||
props: [
|
props: [ "filterFavourites", "filterTrylater", "closeDrawer", "selectedCategory", "hijackGlobalBackEvent", "releaseGlobalBackEvent" ],
|
||||||
"filterFavorites",
|
|
||||||
"filterTrylater",
|
|
||||||
"closeDrawer",
|
|
||||||
"selectedCategory",
|
|
||||||
"hijackGlobalBackEvent",
|
|
||||||
"releaseGlobalBackEvent",
|
|
||||||
],
|
|
||||||
components: {
|
components: {
|
||||||
EditRecipe,
|
EditRecipe,
|
||||||
ViewRecipe,
|
ViewRecipe
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -250,245 +127,228 @@ export default {
|
||||||
rightAction: false,
|
rightAction: false,
|
||||||
sortType: "Natural order",
|
sortType: "Natural order",
|
||||||
deletionDialogActive: false,
|
deletionDialogActive: false,
|
||||||
showFAB: false,
|
showFAB: false
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(["icon", "recipes", "currentComponent"]),
|
...mapState( [ "icon", "recipes", "currentComponent" ] ),
|
||||||
filteredRecipes() {
|
filteredRecipes() {
|
||||||
if (this.filterFavorites) {
|
if ( this.filterFavourites ) {
|
||||||
return this.recipes.filter(
|
return this.recipes.filter( e => e.isFavorite && e.title.toLowerCase().includes( this.searchQuery ) );
|
||||||
(e) =>
|
}
|
||||||
e.isFavorite && e.title.toLowerCase().includes(this.searchQuery)
|
else if ( this.filterTrylater ) {
|
||||||
)
|
return this.recipes.filter( e => !e.tried && e.title.toLowerCase().includes( this.searchQuery ) );
|
||||||
} else if (this.filterTrylater) {
|
}
|
||||||
return this.recipes.filter(
|
else if ( this.selectedCategory ) {
|
||||||
(e) => !e.tried && e.title.toLowerCase().includes(this.searchQuery)
|
return this.recipes.filter( e => e.category === this.selectedCategory && e.title.toLowerCase().includes( this.searchQuery ) );
|
||||||
)
|
}
|
||||||
} else if (this.selectedCategory) {
|
else {
|
||||||
return this.recipes.filter(
|
return this.recipes.filter( e => e.title.toLowerCase().includes( this.searchQuery ) );
|
||||||
(e) =>
|
|
||||||
e.category === this.selectedCategory &&
|
|
||||||
e.title.toLowerCase().includes(this.searchQuery)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
return this.recipes.filter((e) =>
|
|
||||||
e.title.toLowerCase().includes(this.searchQuery)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
noResultFor() {
|
noResultFor() {
|
||||||
if (this.selectedCategory) return " in this category"
|
if ( this.selectedCategory ) return "Your search did not match any recipes in this category";
|
||||||
if (this.filterFavorites) return " in your favorites"
|
if ( this.filterFavourites ) return "Your search did not match any recipes in your favourites";
|
||||||
if (this.filterTrylater) return " in your try later list"
|
if ( this.filterTrylater ) return "Your search did not match any recipes in your try later list";
|
||||||
return ""
|
return "Your search did not match any recipes";
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions(["setCurrentComponentAction", "deleteRecipeAction"]),
|
...mapActions( [ "setCurrentComponentAction", "deleteRecipeAction" ] ),
|
||||||
onPageLoad() {
|
onPageLoad( args ) {
|
||||||
this.filterFavorites
|
const page = args.object;
|
||||||
? this.setComponent("Favorites")
|
page.bindingContext = new Observable();
|
||||||
: this.filterTrylater
|
this.filterFavourites ? this.setComponent( "Favourites" ) : this.filterTrylater ? this.setComponent( "Try Later" ) : this.selectedCategory ? this.setComponent( this.selectedCategory ) : this.setComponent( "EnRecipes" );
|
||||||
? this.setComponent("Try Later")
|
this.showFAB = true;
|
||||||
: this.selectedCategory
|
},
|
||||||
? this.setComponent(this.selectedCategory)
|
onPageUnload() {
|
||||||
: this.setComponent("EnRecipes")
|
this.releaseGlobalBackEvent();
|
||||||
this.showFAB = true
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// HELPERS
|
// HELPERS
|
||||||
showDrawer() {
|
showDrawer() {
|
||||||
utils.showDrawer()
|
utils.showDrawer();
|
||||||
},
|
},
|
||||||
openSearch() {
|
openSearch() {
|
||||||
this.showSearch = true
|
this.showSearch = true;
|
||||||
this.showFAB = false
|
this.showFAB = false;
|
||||||
this.hijackLocalBackEvent()
|
this.hijackLocalBackEvent();
|
||||||
},
|
},
|
||||||
closeSearch() {
|
closeSearch() {
|
||||||
if (this.searchQuery) this.updateFilter()
|
if ( this.searchQuery ) this.updateFilter();
|
||||||
this.searchQuery = ""
|
this.searchQuery = "";
|
||||||
Utils.ad.dismissSoftInput()
|
Utils.ad.dismissSoftInput();
|
||||||
this.showSearch = false
|
this.showSearch = false;
|
||||||
this.showFAB = true
|
this.showFAB = true;
|
||||||
this.releaseLocalBackEvent()
|
this.releaseLocalBackEvent();
|
||||||
},
|
},
|
||||||
setComponent(comp) {
|
setComponent( comp ) {
|
||||||
this.setCurrentComponentAction(comp)
|
this.setCurrentComponentAction( comp );
|
||||||
this.hijackGlobalBackEvent()
|
this.hijackGlobalBackEvent();
|
||||||
},
|
},
|
||||||
clearSearch() {
|
clearSearch() {
|
||||||
if (this.searchQuery !== "") {
|
if ( this.searchQuery !== "" ) {
|
||||||
this.updateFilter()
|
this.updateFilter();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
formattedTotalTime(prepTime, cookTime) {
|
formattedTotalTime( prepTime, cookTime ) {
|
||||||
let t1 = prepTime.split(":")
|
let t1 = prepTime.split( ":" );
|
||||||
let t2 = cookTime.split(":")
|
let t2 = cookTime.split( ":" );
|
||||||
let h = parseInt(t1[0]) + parseInt(t2[0])
|
let h = parseInt( t1[ 0 ] ) + parseInt( t2[ 0 ] );
|
||||||
let m = parseInt(t1[1]) + parseInt(t2[1])
|
let m = parseInt( t1[ 1 ] ) + parseInt( t2[ 1 ] );
|
||||||
|
let hr = localize( 'hr' )
|
||||||
|
let min = localize( 'min' )
|
||||||
return {
|
return {
|
||||||
time: h ? (m ? `${h} hr ${m} min` : `${h} hr`) : `${m} min`,
|
time: h ? ( m ? `${h} ${hr} ${m} ${min}` : `${h} ${hr}` ) : `${m} ${min}`,
|
||||||
duration: `${h}${m}`,
|
duration: `${h}${m}`
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
onScroll(args) {
|
onScroll( args ) {
|
||||||
this.viewIsScrolled = args.scrollOffset ? true : false
|
this.viewIsScrolled = args.scrollOffset ? true : false;
|
||||||
},
|
},
|
||||||
|
|
||||||
// NAVIGATION HANDLERS
|
// NAVIGATION HANDLERS
|
||||||
hijackLocalBackEvent() {
|
hijackLocalBackEvent() {
|
||||||
this.releaseGlobalBackEvent()
|
this.releaseGlobalBackEvent();
|
||||||
AndroidApplication.on(
|
AndroidApplication.on( AndroidApplication.activityBackPressedEvent, this.searchBackEvent );
|
||||||
AndroidApplication.activityBackPressedEvent,
|
|
||||||
this.searchBackEvent
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
releaseLocalBackEvent() {
|
releaseLocalBackEvent() {
|
||||||
AndroidApplication.off(
|
AndroidApplication.off( AndroidApplication.activityBackPressedEvent, this.searchBackEvent );
|
||||||
AndroidApplication.activityBackPressedEvent,
|
this.hijackGlobalBackEvent();
|
||||||
this.searchBackEvent
|
|
||||||
)
|
|
||||||
this.hijackGlobalBackEvent()
|
|
||||||
},
|
},
|
||||||
searchBackEvent(args) {
|
searchBackEvent( args ) {
|
||||||
args.cancel = true
|
args.cancel = true;
|
||||||
this.closeDrawer()
|
this.closeDrawer();
|
||||||
this.closeSearch()
|
this.closeSearch();
|
||||||
},
|
},
|
||||||
addRecipe() {
|
addRecipe() {
|
||||||
this.showFAB = false
|
this.showFAB = false;
|
||||||
this.releaseGlobalBackEvent()
|
this.releaseGlobalBackEvent();
|
||||||
this.$navigateTo(EditRecipe, {
|
this.$navigateTo( EditRecipe, {
|
||||||
props: {
|
props: {
|
||||||
selectedCategory: this.selectedCategory,
|
selectedCategory: this.selectedCategory,
|
||||||
filterFavorites: this.filterFavorites,
|
filterFavourites: this.filterFavourites
|
||||||
|
}
|
||||||
|
} );
|
||||||
},
|
},
|
||||||
})
|
viewRecipe( recipeID ) {
|
||||||
},
|
this.showFAB = false;
|
||||||
viewRecipe(recipeID) {
|
this.$navigateTo( ViewRecipe, {
|
||||||
this.showFAB = false
|
|
||||||
this.$navigateTo(ViewRecipe, {
|
|
||||||
props: {
|
props: {
|
||||||
filterTrylater: this.filterTrylater,
|
filterTrylater: this.filterTrylater,
|
||||||
recipeID,
|
recipeID
|
||||||
},
|
},
|
||||||
backstackVisible: false,
|
backstackVisible: false
|
||||||
})
|
} );
|
||||||
},
|
},
|
||||||
|
|
||||||
// LIST HANDLERS
|
// LIST HANDLERS
|
||||||
sortDialog() {
|
sortDialog() {
|
||||||
this.releaseGlobalBackEvent()
|
this.releaseGlobalBackEvent();
|
||||||
this.$showModal(ActionDialog, {
|
this.$showModal( ActionDialog, {
|
||||||
props: {
|
props: {
|
||||||
title: "Sort by",
|
title: "Sort by",
|
||||||
list: ["Natural order", "Title", "Duration", "Last modified"],
|
list: [ "Natural order", "Title", "Duration", "Last modified" ],
|
||||||
height: "192",
|
height: "192"
|
||||||
},
|
|
||||||
}).then((action) => {
|
|
||||||
if (action && action !== "Cancel" && this.sortType !== action) {
|
|
||||||
this.sortType = action
|
|
||||||
this.updateSort()
|
|
||||||
}
|
}
|
||||||
this.hijackGlobalBackEvent()
|
} ).then( action => {
|
||||||
})
|
if ( action && action !== "Cancel" && this.sortType !== action ) {
|
||||||
|
this.sortType = action;
|
||||||
|
this.updateSort();
|
||||||
|
}
|
||||||
|
this.hijackGlobalBackEvent();
|
||||||
|
} );
|
||||||
},
|
},
|
||||||
updateSort() {
|
updateSort() {
|
||||||
let listView = this.$refs.listView.nativeView
|
let listView = this.$refs.listView.nativeView;
|
||||||
listView.sortingFunction = undefined
|
listView.sortingFunction = undefined;
|
||||||
listView.sortingFunction = this.sortFunction
|
listView.sortingFunction = this.sortFunction;
|
||||||
},
|
},
|
||||||
sortFunction(item, otherItem) {
|
sortFunction( item, otherItem ) {
|
||||||
const titleOrder = item.title
|
const titleOrder = item.title.toLowerCase().localeCompare( otherItem.title.toLowerCase(), "en", {
|
||||||
.toLowerCase()
|
ignorePunctuation: true
|
||||||
.localeCompare(otherItem.title.toLowerCase(), "en", {
|
} );
|
||||||
ignorePunctuation: true,
|
let d1 = this.formattedTotalTime( item.prepTime, item.cookTime ).duration;
|
||||||
})
|
let d2 = this.formattedTotalTime( otherItem.prepTime, otherItem.cookTime ).duration;
|
||||||
let d1 = this.formattedTotalTime(item.prepTime, item.cookTime).duration
|
let ld1 = new Date( item.lastModified );
|
||||||
let d2 = this.formattedTotalTime(otherItem.prepTime, otherItem.cookTime)
|
let ld2 = new Date( otherItem.lastModified );
|
||||||
.duration
|
switch ( this.sortType ) {
|
||||||
let ld1 = new Date(item.lastModified)
|
|
||||||
let ld2 = new Date(otherItem.lastModified)
|
|
||||||
switch (this.sortType) {
|
|
||||||
case "Title":
|
case "Title":
|
||||||
return titleOrder > 0 ? -1 : titleOrder < 0 ? 1 : 0
|
return titleOrder > 0 ? -1 : titleOrder < 0 ? 1 : 0;
|
||||||
break
|
break;
|
||||||
case "Duration":
|
case "Duration":
|
||||||
return d1 > d2 ? -1 : d1 < d2 ? 1 : 0
|
return d1 > d2 ? -1 : d1 < d2 ? 1 : 0;
|
||||||
break
|
break;
|
||||||
case "Last modified":
|
case "Last modified":
|
||||||
return ld1 < ld2 ? -1 : ld1 > ld2 ? 1 : 0
|
return ld1 < ld2 ? -1 : ld1 > ld2 ? 1 : 0;
|
||||||
break
|
break;
|
||||||
default:
|
default:
|
||||||
return 0
|
return 0;
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
updateFilter() {
|
updateFilter() {
|
||||||
let listView = this.$refs.listView.nativeView
|
let listView = this.$refs.listView.nativeView;
|
||||||
setTimeout((e) => {
|
setTimeout( e => {
|
||||||
listView.filteringFunction = undefined
|
listView.filteringFunction = undefined;
|
||||||
listView.filteringFunction = this.filterFunction
|
listView.filteringFunction = this.filterFunction;
|
||||||
}, 1)
|
}, 1 );
|
||||||
},
|
},
|
||||||
filterFunction(item) {
|
filterFunction( item ) {
|
||||||
if (this.filterFavorites) {
|
if ( this.filterFavourites ) {
|
||||||
return item.isFavorite
|
return item.isFavorite ? item.title.toLowerCase().includes( this.searchQuery ) : false;
|
||||||
? item.title.toLowerCase().includes(this.searchQuery)
|
}
|
||||||
: false
|
else if ( this.filterTrylater ) {
|
||||||
} else if (this.filterTrylater) {
|
return item.tried ? false : item.title.toLowerCase().includes( this.searchQuery );
|
||||||
return item.tried
|
}
|
||||||
? false
|
else if ( this.selectedCategory ) {
|
||||||
: item.title.toLowerCase().includes(this.searchQuery)
|
return item.category === this.selectedCategory ? item.title.toLowerCase().includes( this.searchQuery ) : false;
|
||||||
} else if (this.selectedCategory) {
|
}
|
||||||
return item.category === this.selectedCategory
|
else {
|
||||||
? item.title.toLowerCase().includes(this.searchQuery)
|
return item.title.toLowerCase().includes( this.searchQuery );
|
||||||
: false
|
|
||||||
} else {
|
|
||||||
return item.title.toLowerCase().includes(this.searchQuery)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
onSwiping( {
|
||||||
onSwiping({ data, object }) {
|
data,
|
||||||
const swipeLimits = data.swipeLimits
|
object
|
||||||
const swipeView = object
|
} ) {
|
||||||
const rightItem = swipeView.getViewById("delete-action")
|
const swipeLimits = data.swipeLimits;
|
||||||
swipeLimits.right = rightItem.getMeasuredWidth() - 12
|
const swipeView = object;
|
||||||
swipeLimits.threshold = swipeLimits.right - 6
|
const rightItem = swipeView.getViewById( "delete-action" );
|
||||||
if (data.x < -swipeLimits.threshold) {
|
swipeLimits.right = rightItem.getMeasuredWidth() - 12;
|
||||||
this.rightAction = true
|
swipeLimits.threshold = swipeLimits.right - 6;
|
||||||
swipeView.notifySwipeToExecuteFinished()
|
if ( data.x < -swipeLimits.threshold ) {
|
||||||
|
this.rightAction = true;
|
||||||
|
swipeView.notifySwipeToExecuteFinished();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSwipeEnded({ index }) {
|
onSwipeEnded( {
|
||||||
let recipeID = this.recipes[index].id
|
index
|
||||||
if (this.rightAction && !this.deletionDialogActive)
|
} ) {
|
||||||
this.deleteRecipe(index, recipeID)
|
let recipeID = this.recipes[ index ].id;
|
||||||
this.rightAction = false
|
if ( this.rightAction && !this.deletionDialogActive ) this.deleteRecipe( index, recipeID );
|
||||||
|
this.rightAction = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
// DATA HANDLERS
|
// DATA HANDLERS
|
||||||
deleteRecipe(index, recipeID) {
|
deleteRecipe( index, recipeID ) {
|
||||||
this.deletionDialogActive = true
|
this.deletionDialogActive = true;
|
||||||
this.$showModal(ConfirmDialog, {
|
this.$showModal( ConfirmDialog, {
|
||||||
props: {
|
props: {
|
||||||
title: "Delete recipe",
|
title: localize( "Delete recipe?" ),
|
||||||
description: `Are you sure you want to delete the recipe "${this.recipes[index].title}"?`,
|
description: `${localize('Are you sure you want to delete the recipe')} "${this.recipes[index].title}"?`,
|
||||||
cancelButtonText: "CANCEL",
|
cancelButtonText: "CANCEL",
|
||||||
okButtonText: "DELETE",
|
okButtonText: "DELETE"
|
||||||
},
|
}
|
||||||
}).then((action) => {
|
} ).then( action => {
|
||||||
if (action) {
|
if ( action ) {
|
||||||
this.deleteRecipeAction({ index, id: recipeID })
|
this.deleteRecipeAction( {
|
||||||
|
index,
|
||||||
|
id: recipeID
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
this.deletionDialogActive = false;
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
this.deletionDialogActive = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.showFAB = true
|
this.showFAB = true;
|
||||||
},
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,90 +1,43 @@
|
||||||
<template>
|
<template>
|
||||||
<Page @loaded="onPageLoad">
|
<Page @loaded="onPageLoad">
|
||||||
<ActionBar flat="true">
|
<ActionBar flat="true">
|
||||||
<GridLayout rows="*" columns="auto, *, auto">
|
<GridLayout rows="*" columns="auto, *, auto">
|
||||||
<MDButton
|
<MDButton class="bx left" variant="text" :text="icon.menu" automationText="Back" @tap="showDrawer" col="0" />
|
||||||
class="bx left"
|
<Label class="title orkm" :text="'Meal Planner' | L" col="1" />
|
||||||
variant="text"
|
<MDButton class="bx left" variant="text" :text="icon.today" automationText="today" @tap="goToToday" col="2" />
|
||||||
:text="icon.menu"
|
|
||||||
automationText="Back"
|
|
||||||
@tap="showDrawer"
|
|
||||||
col="0"
|
|
||||||
/>
|
|
||||||
<Label class="title orkm" text="Meal Planner" col="1" />
|
|
||||||
<MDButton
|
|
||||||
class="bx left"
|
|
||||||
variant="text"
|
|
||||||
:text="icon.today"
|
|
||||||
automationText="today"
|
|
||||||
@tap="goToToday"
|
|
||||||
col="2"
|
|
||||||
/>
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</ActionBar>
|
</ActionBar>
|
||||||
<GridLayout rows="280, *">
|
<GridLayout rows="280, *">
|
||||||
<RadCalendar
|
<RadCalendar :androidElevation="viewIsScrolled ? 4 : 0" class="orkm" row="0" ref="calendar" @loaded="onCalendarLoad" @dateSelected="onDateSelected" :viewMode="viewMode" :transitionMode="transitionMode" :selectionMode="selectionMode"
|
||||||
:androidElevation="viewIsScrolled ? 4 : 0"
|
:eventsViewMode="eventsViewMode" :eventSource="getMealPlans"></RadCalendar>
|
||||||
class="orkm"
|
|
||||||
row="0"
|
|
||||||
ref="calendar"
|
|
||||||
locale="en-US"
|
|
||||||
@loaded="onCalendarLoad"
|
|
||||||
@dateSelected="onDateSelected"
|
|
||||||
:viewMode="viewMode"
|
|
||||||
:transitionMode="transitionMode"
|
|
||||||
:selectionMode="selectionMode"
|
|
||||||
:eventsViewMode="eventsViewMode"
|
|
||||||
:eventSource="getMealPlans"
|
|
||||||
></RadCalendar>
|
|
||||||
<ScrollView row="1" width="100%" height="100%" @scroll="onScroll">
|
<ScrollView row="1" width="100%" height="100%" @scroll="onScroll">
|
||||||
<StackLayout class="dayPlan">
|
<StackLayout class="dayPlan">
|
||||||
<StackLayout
|
<StackLayout v-for="(mealType, index) in mealTimes" :key="'mealType' + index" class="plansContainer" :class="mealType">
|
||||||
v-for="(mealType, index) in mealTimes"
|
|
||||||
:key="'mealType' + index"
|
|
||||||
class="plansContainer"
|
|
||||||
:class="mealType"
|
|
||||||
>
|
|
||||||
<GridLayout columns="*, auto" class="header">
|
<GridLayout columns="*, auto" class="header">
|
||||||
<Label col="0" class="periodLabel orkm" :text="mealType" />
|
<Label col="0" class="periodLabel orkm" :text="mealType | L" />
|
||||||
<MDButton
|
<MDButton col="1" variant="text" class="bx addMeal" :text="icon.plus" @tap="addRecipe(mealType)" />
|
||||||
col="1"
|
|
||||||
variant="text"
|
|
||||||
class="bx addMeal"
|
|
||||||
:text="icon.plus"
|
|
||||||
@tap="addRecipe(mealType)"
|
|
||||||
/>
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<GridLayout
|
<GridLayout class="recipes" columns="*, auto" v-for="(recipeID, index) in getRecipes[mealType]" :key="mealType + index">
|
||||||
class="recipes"
|
|
||||||
columns="*, auto"
|
|
||||||
v-for="(recipeID, index) in getRecipes[mealType]"
|
|
||||||
:key="mealType + index"
|
|
||||||
>
|
|
||||||
<MDRipple @tap="viewRecipe(recipeID)" />
|
<MDRipple @tap="viewRecipe(recipeID)" />
|
||||||
<Label
|
<Label verticalAlignment="center" class="recipeTitle" col="0" :text="getRecipeTitle(recipeID)" textWrap="true" />
|
||||||
verticalAlignment="center"
|
<MDButton variant="text" col="1" class="bx closeBtn" :text="icon.close" @tap="removeRecipe(mealType, recipeID)" />
|
||||||
class="recipeTitle"
|
|
||||||
col="0"
|
|
||||||
:text="getRecipeTitle(recipeID)"
|
|
||||||
textWrap="true"
|
|
||||||
/>
|
|
||||||
<MDButton
|
|
||||||
variant="text"
|
|
||||||
col="1"
|
|
||||||
class="bx closeBtn"
|
|
||||||
:text="icon.close"
|
|
||||||
@tap="removeRecipe(mealType, recipeID)"
|
|
||||||
/>
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { ApplicationSettings, Color, Page } from "@nativescript/core"
|
import {
|
||||||
|
ApplicationSettings,
|
||||||
|
Color,
|
||||||
|
Page,
|
||||||
|
Observable,
|
||||||
|
Device
|
||||||
|
}
|
||||||
|
from "@nativescript/core"
|
||||||
import {
|
import {
|
||||||
CalendarViewMode,
|
CalendarViewMode,
|
||||||
CalendarTransitionMode,
|
CalendarTransitionMode,
|
||||||
|
@ -96,9 +49,14 @@ import {
|
||||||
CalendarCellAlignment,
|
CalendarCellAlignment,
|
||||||
CellStyle,
|
CellStyle,
|
||||||
CalendarEventsViewMode,
|
CalendarEventsViewMode,
|
||||||
CalendarEvent,
|
CalendarEvent
|
||||||
} from "nativescript-ui-calendar"
|
}
|
||||||
import { mapState, mapActions } from "vuex"
|
from "nativescript-ui-calendar"
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions
|
||||||
|
}
|
||||||
|
from "vuex"
|
||||||
|
|
||||||
import ViewRecipe from "./ViewRecipe.vue"
|
import ViewRecipe from "./ViewRecipe.vue"
|
||||||
|
|
||||||
|
@ -112,7 +70,7 @@ export default {
|
||||||
return {
|
return {
|
||||||
viewIsScrolled: false,
|
viewIsScrolled: false,
|
||||||
appTheme: "Light",
|
appTheme: "Light",
|
||||||
mealTimes: ["breakfast", "lunch", "dinner", "snacks"],
|
mealTimes: [ "breakfast", "lunch", "dinner", "snacks" ],
|
||||||
eventList: [],
|
eventList: [],
|
||||||
selectedDayMealPlans: [],
|
selectedDayMealPlans: [],
|
||||||
viewMode: CalendarViewMode.Month,
|
viewMode: CalendarViewMode.Month,
|
||||||
|
@ -120,18 +78,18 @@ export default {
|
||||||
selectionMode: CalendarSelectionMode.Single,
|
selectionMode: CalendarSelectionMode.Single,
|
||||||
eventsViewMode: CalendarEventsViewMode.None,
|
eventsViewMode: CalendarEventsViewMode.None,
|
||||||
color: {
|
color: {
|
||||||
white: new Color("#ffffff"),
|
white: new Color( "#ffffff" ),
|
||||||
gray1: new Color("#f1f3f5"),
|
gray1: new Color( "#f1f3f5" ),
|
||||||
gray2: new Color("#e9ecef"),
|
gray2: new Color( "#e9ecef" ),
|
||||||
gray3: new Color("#dee2e6"),
|
gray3: new Color( "#dee2e6" ),
|
||||||
gray4: new Color("#ced4da"),
|
gray4: new Color( "#ced4da" ),
|
||||||
gray5: new Color("#adb5bd"),
|
gray5: new Color( "#adb5bd" ),
|
||||||
gray6: new Color("#868e96"),
|
gray6: new Color( "#868e96" ),
|
||||||
gray7: new Color("#495057"),
|
gray7: new Color( "#495057" ),
|
||||||
gray8: new Color("#343a40"),
|
gray8: new Color( "#343a40" ),
|
||||||
gray9: new Color("#212529"),
|
gray9: new Color( "#212529" ),
|
||||||
black: new Color("#111111"),
|
black: new Color( "#111111" ),
|
||||||
orange: new Color("#ff5200"),
|
orange: new Color( "#ff5200" ),
|
||||||
breakfast: "#ffb180",
|
breakfast: "#ffb180",
|
||||||
lunch: "#ceff80",
|
lunch: "#ceff80",
|
||||||
dinner: "#80ceff",
|
dinner: "#80ceff",
|
||||||
|
@ -143,45 +101,45 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(["icon", "recipes", "mealPlans"]),
|
...mapState( [ "icon", "recipes", "mealPlans" ] ),
|
||||||
isLightMode() {
|
isLightMode() {
|
||||||
return this.appTheme === "Light"
|
return this.appTheme === "Light"
|
||||||
},
|
},
|
||||||
monthViewStyle() {
|
monthViewStyle() {
|
||||||
const monthViewStyle = new CalendarMonthViewStyle()
|
const monthViewStyle = new CalendarMonthViewStyle()
|
||||||
monthViewStyle.backgroundColor = this.isLightMode
|
monthViewStyle.backgroundColor = this.isLightMode ?
|
||||||
? this.color.gray1
|
this.color.gray1 :
|
||||||
: this.color.gray9
|
this.color.gray9
|
||||||
monthViewStyle.showTitle = true
|
monthViewStyle.showTitle = true
|
||||||
monthViewStyle.showWeekNumbers = false
|
monthViewStyle.showWeekNumbers = false
|
||||||
monthViewStyle.showDayNames = true
|
monthViewStyle.showDayNames = true
|
||||||
|
|
||||||
const titleCellStyle = new DayCellStyle()
|
const titleCellStyle = new DayCellStyle()
|
||||||
titleCellStyle.cellBackgroundColor = this.isLightMode
|
titleCellStyle.cellBackgroundColor = this.isLightMode ?
|
||||||
? this.color.gray2
|
this.color.gray2 :
|
||||||
: this.color.black
|
this.color.black
|
||||||
titleCellStyle.cellBorderWidth = 1
|
titleCellStyle.cellBorderWidth = 1
|
||||||
titleCellStyle.cellBorderColor = this.isLightMode
|
titleCellStyle.cellBorderColor = this.isLightMode ?
|
||||||
? this.color.gray2
|
this.color.gray2 :
|
||||||
: this.color.black
|
this.color.black
|
||||||
titleCellStyle.cellTextSize = 16
|
titleCellStyle.cellTextSize = 16
|
||||||
titleCellStyle.cellTextColor = this.isLightMode
|
titleCellStyle.cellTextColor = this.isLightMode ?
|
||||||
? this.color.gray9
|
this.color.gray9 :
|
||||||
: this.color.gray1
|
this.color.gray1
|
||||||
titleCellStyle.cellTextFontName = this.appFontMedium
|
titleCellStyle.cellTextFontName = this.appFontMedium
|
||||||
monthViewStyle.titleCellStyle = titleCellStyle
|
monthViewStyle.titleCellStyle = titleCellStyle
|
||||||
|
|
||||||
const dayNameCellStyle = new CellStyle()
|
const dayNameCellStyle = new CellStyle()
|
||||||
dayNameCellStyle.cellBackgroundColor = this.isLightMode
|
dayNameCellStyle.cellBackgroundColor = this.isLightMode ?
|
||||||
? this.color.gray2
|
this.color.gray2 :
|
||||||
: this.color.black
|
this.color.black
|
||||||
dayNameCellStyle.cellTextColor = this.isLightMode
|
dayNameCellStyle.cellTextColor = this.isLightMode ?
|
||||||
? this.color.gray9
|
this.color.gray9 :
|
||||||
: this.color.gray1
|
this.color.gray1
|
||||||
dayNameCellStyle.cellBorderWidth = 1
|
dayNameCellStyle.cellBorderWidth = 1
|
||||||
dayNameCellStyle.cellBorderColor = this.isLightMode
|
dayNameCellStyle.cellBorderColor = this.isLightMode ?
|
||||||
? this.color.gray2
|
this.color.gray2 :
|
||||||
: this.color.black
|
this.color.black
|
||||||
dayNameCellStyle.cellTextSize = 10
|
dayNameCellStyle.cellTextSize = 10
|
||||||
dayNameCellStyle.cellAlignment = CalendarCellAlignment.Center
|
dayNameCellStyle.cellAlignment = CalendarCellAlignment.Center
|
||||||
dayNameCellStyle.cellTextFontName = this.appFontMedium
|
dayNameCellStyle.cellTextFontName = this.appFontMedium
|
||||||
|
@ -194,46 +152,46 @@ export default {
|
||||||
dayCellStyle.eventFontStyle = CalendarFontStyle.Bold
|
dayCellStyle.eventFontStyle = CalendarFontStyle.Bold
|
||||||
dayCellStyle.eventTextSize = 8
|
dayCellStyle.eventTextSize = 8
|
||||||
dayCellStyle.cellTextSize = 16
|
dayCellStyle.cellTextSize = 16
|
||||||
dayCellStyle.cellTextColor = this.isLightMode
|
dayCellStyle.cellTextColor = this.isLightMode ?
|
||||||
? this.color.gray9
|
this.color.gray9 :
|
||||||
: this.color.gray1
|
this.color.gray1
|
||||||
dayCellStyle.cellAlignment = CalendarCellAlignment.Bottom
|
dayCellStyle.cellAlignment = CalendarCellAlignment.Bottom
|
||||||
dayCellStyle.cellBackgroundColor = this.isLightMode
|
dayCellStyle.cellBackgroundColor = this.isLightMode ?
|
||||||
? this.color.gray1
|
this.color.gray1 :
|
||||||
: this.color.gray9
|
this.color.gray9
|
||||||
dayCellStyle.cellTextFontName = this.appFontRegular
|
dayCellStyle.cellTextFontName = this.appFontRegular
|
||||||
dayCellStyle.cellBorderWidth = 1
|
dayCellStyle.cellBorderWidth = 1
|
||||||
dayCellStyle.cellBorderColor = this.isLightMode
|
dayCellStyle.cellBorderColor = this.isLightMode ?
|
||||||
? this.color.gray2
|
this.color.gray2 :
|
||||||
: this.color.black
|
this.color.black
|
||||||
monthViewStyle.dayCellStyle = dayCellStyle
|
monthViewStyle.dayCellStyle = dayCellStyle
|
||||||
|
|
||||||
const todayCellStyle = new DayCellStyle()
|
const todayCellStyle = new DayCellStyle()
|
||||||
todayCellStyle.cellBackgroundColor = this.isLightMode
|
todayCellStyle.cellBackgroundColor = this.isLightMode ?
|
||||||
? this.color.gray1
|
this.color.gray1 :
|
||||||
: this.color.gray9
|
this.color.gray9
|
||||||
todayCellStyle.cellTextColor = this.color.orange
|
todayCellStyle.cellTextColor = this.color.orange
|
||||||
todayCellStyle.cellBorderWidth = 1
|
todayCellStyle.cellBorderWidth = 1
|
||||||
todayCellStyle.cellTextFontName = this.appFontMedium
|
todayCellStyle.cellTextFontName = this.appFontMedium
|
||||||
todayCellStyle.cellTextFontStyle = CalendarFontStyle.Bold
|
todayCellStyle.cellTextFontStyle = CalendarFontStyle.Bold
|
||||||
todayCellStyle.cellTextSize = 16
|
todayCellStyle.cellTextSize = 16
|
||||||
todayCellStyle.cellAlignment = CalendarCellAlignment.Bottom
|
todayCellStyle.cellAlignment = CalendarCellAlignment.Bottom
|
||||||
todayCellStyle.cellBorderColor = this.isLightMode
|
todayCellStyle.cellBorderColor = this.isLightMode ?
|
||||||
? this.color.gray2
|
this.color.gray2 :
|
||||||
: this.color.black
|
this.color.black
|
||||||
monthViewStyle.todayCellStyle = todayCellStyle
|
monthViewStyle.todayCellStyle = todayCellStyle
|
||||||
|
|
||||||
const selectedCellStyle = new DayCellStyle()
|
const selectedCellStyle = new DayCellStyle()
|
||||||
selectedCellStyle.eventTextSize = 1
|
selectedCellStyle.eventTextSize = 1
|
||||||
selectedCellStyle.cellAlignment = CalendarCellAlignment.Bottom
|
selectedCellStyle.cellAlignment = CalendarCellAlignment.Bottom
|
||||||
selectedCellStyle.cellBackgroundColor = this.isLightMode
|
selectedCellStyle.cellBackgroundColor = this.isLightMode ?
|
||||||
? this.color.white
|
this.color.white :
|
||||||
: this.color.gray8
|
this.color.gray8
|
||||||
selectedCellStyle.cellBorderWidth = 1
|
selectedCellStyle.cellBorderWidth = 1
|
||||||
selectedCellStyle.cellBorderColor = this.color.orange
|
selectedCellStyle.cellBorderColor = this.color.orange
|
||||||
selectedCellStyle.cellTextColor = this.isLightMode
|
selectedCellStyle.cellTextColor = this.isLightMode ?
|
||||||
? this.color.gray9
|
this.color.gray9 :
|
||||||
: this.color.gray1
|
this.color.gray1
|
||||||
selectedCellStyle.cellTextFontName = this.appFontMedium
|
selectedCellStyle.cellTextFontName = this.appFontMedium
|
||||||
selectedCellStyle.cellTextFontStyle = CalendarFontStyle.Bold
|
selectedCellStyle.cellTextFontStyle = CalendarFontStyle.Bold
|
||||||
selectedCellStyle.cellTextSize = 16
|
selectedCellStyle.cellTextSize = 16
|
||||||
|
@ -242,31 +200,32 @@ export default {
|
||||||
return monthViewStyle
|
return monthViewStyle
|
||||||
},
|
},
|
||||||
getRecipes() {
|
getRecipes() {
|
||||||
if (this.selectedDayMealPlans.length) {
|
if ( this.selectedDayMealPlans.length ) {
|
||||||
return this.selectedDayMealPlans.reduce((acc, e) => {
|
return this.selectedDayMealPlans.reduce( ( acc, e ) => {
|
||||||
switch (e.startDate.getHours()) {
|
switch ( e.startDate.getHours() ) {
|
||||||
case 0: //breakfast
|
case 0: //breakfast
|
||||||
acc["breakfast"] = [...(acc["breakfast"] || []), e.title]
|
acc[ "breakfast" ] = [ ...( acc[ "breakfast" ] || [] ), e.title ]
|
||||||
break
|
break
|
||||||
case 5: //lunch
|
case 5: //lunch
|
||||||
acc["lunch"] = [...(acc["lunch"] || []), e.title]
|
acc[ "lunch" ] = [ ...( acc[ "lunch" ] || [] ), e.title ]
|
||||||
break
|
break
|
||||||
case 10: //dinner
|
case 10: //dinner
|
||||||
acc["dinner"] = [...(acc["dinner"] || []), e.title]
|
acc[ "dinner" ] = [ ...( acc[ "dinner" ] || [] ), e.title ]
|
||||||
break
|
break
|
||||||
case 15: //snacks
|
case 15: //snacks
|
||||||
acc["snacks"] = [...(acc["snacks"] || []), e.title]
|
acc[ "snacks" ] = [ ...( acc[ "snacks" ] || [] ), e.title ]
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
return acc
|
return acc
|
||||||
}, {})
|
}, {} )
|
||||||
} else return 0
|
}
|
||||||
|
else return 0
|
||||||
},
|
},
|
||||||
getMealPlans() {
|
getMealPlans() {
|
||||||
const getDate = (date) => {
|
const getDate = ( date ) => {
|
||||||
let d = new Date(date)
|
let d = new Date( date )
|
||||||
let result = new Date(
|
let result = new Date(
|
||||||
d.getFullYear(),
|
d.getFullYear(),
|
||||||
d.getMonth(),
|
d.getMonth(),
|
||||||
|
@ -276,40 +235,43 @@ export default {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
let events = []
|
let events = []
|
||||||
this.mealPlans.forEach((plan) => {
|
this.mealPlans.forEach( ( plan ) => {
|
||||||
let e = new CalendarEvent(
|
let e = new CalendarEvent(
|
||||||
plan.title,
|
plan.title,
|
||||||
getDate(plan.startDate),
|
getDate( plan.startDate ),
|
||||||
getDate(plan.endDate),
|
getDate( plan.endDate ),
|
||||||
false,
|
false,
|
||||||
new Color(plan.eventColor)
|
new Color( plan.eventColor )
|
||||||
)
|
)
|
||||||
events = [...events, e]
|
events = [ ...events, e ]
|
||||||
})
|
} )
|
||||||
return events
|
return events
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions([
|
...mapActions( [
|
||||||
"setCurrentComponentAction",
|
"setCurrentComponentAction",
|
||||||
"initializeMealPlans",
|
"initializeMealPlans",
|
||||||
"addMealPlanAction",
|
"addMealPlanAction",
|
||||||
"deleteMealPlanAction",
|
"deleteMealPlanAction",
|
||||||
]),
|
] ),
|
||||||
onPageLoad(args) {
|
onPageLoad( args ) {
|
||||||
this.setCurrentComponentAction("MealPlanner")
|
const page = args.object;
|
||||||
|
page.bindingContext = new Observable();
|
||||||
|
this.setCurrentComponentAction( "MealPlanner" )
|
||||||
},
|
},
|
||||||
onCalendarLoad(args) {
|
onCalendarLoad( args ) {
|
||||||
|
args.object.locale = `${Device.language}-${Device.language.toUpperCase()}`
|
||||||
args.object.monthViewStyle = this.monthViewStyle
|
args.object.monthViewStyle = this.monthViewStyle
|
||||||
args.object.android
|
args.object.android
|
||||||
.getGestureManager()
|
.getGestureManager()
|
||||||
.setDoubleTapToChangeDisplayMode(false)
|
.setDoubleTapToChangeDisplayMode( false )
|
||||||
args.object.android
|
args.object.android
|
||||||
.getGestureManager()
|
.getGestureManager()
|
||||||
.setPinchCloseToChangeDisplayMode(false)
|
.setPinchCloseToChangeDisplayMode( false )
|
||||||
if (args.object.selectedDate == null)
|
if ( args.object.selectedDate == null )
|
||||||
args.object.selectedDate = new Date()
|
args.object.selectedDate = new Date()
|
||||||
if (args.object.nativeView.getEventAdapter()) {
|
if ( args.object.nativeView.getEventAdapter() ) {
|
||||||
args.object.nativeView
|
args.object.nativeView
|
||||||
.getEventAdapter()
|
.getEventAdapter()
|
||||||
.getRenderer()
|
.getRenderer()
|
||||||
|
@ -323,102 +285,102 @@ export default {
|
||||||
showDrawer() {
|
showDrawer() {
|
||||||
utils.showDrawer()
|
utils.showDrawer()
|
||||||
},
|
},
|
||||||
onScroll(args) {
|
onScroll( args ) {
|
||||||
this.viewIsScrolled = args.scrollY ? true : false
|
this.viewIsScrolled = args.scrollY ? true : false
|
||||||
},
|
},
|
||||||
getDate(index) {
|
getDate( index ) {
|
||||||
let date = new Date()
|
let date = new Date()
|
||||||
date.setDate(date.getDate() + index)
|
date.setDate( date.getDate() + index )
|
||||||
return date.getTime()
|
return date.getTime()
|
||||||
},
|
},
|
||||||
getDateString(days) {
|
getDateString( days ) {
|
||||||
let date = new Date()
|
let date = new Date()
|
||||||
date.setDate(date.getDate() + days)
|
date.setDate( date.getDate() + days )
|
||||||
return date.toDateString().slice(0, -5)
|
return date.toDateString().slice( 0, -5 )
|
||||||
},
|
},
|
||||||
getRecipeTitle(id) {
|
getRecipeTitle( id ) {
|
||||||
let recipe = this.recipes.filter((e) => e.id === id)[0]
|
let recipe = this.recipes.filter( ( e ) => e.id === id )[ 0 ]
|
||||||
return recipe ? recipe.title : "[Deleted Recipe]"
|
return recipe ? recipe.title : "[Deleted Recipe]"
|
||||||
},
|
},
|
||||||
|
|
||||||
// NAVIGATION HANDLERS
|
// NAVIGATION HANDLERS
|
||||||
viewRecipe(recipeID) {
|
viewRecipe( recipeID ) {
|
||||||
let recipe = this.recipes.filter((e) => e.id === recipeID)[0]
|
let recipe = this.recipes.filter( ( e ) => e.id === recipeID )[ 0 ]
|
||||||
if (recipe) {
|
if ( recipe ) {
|
||||||
this.$navigateTo(ViewRecipe, {
|
this.$navigateTo( ViewRecipe, {
|
||||||
props: {
|
props: {
|
||||||
filterTrylater: true,
|
filterTrylater: true,
|
||||||
recipeID,
|
recipeID,
|
||||||
},
|
},
|
||||||
backstackVisible: false,
|
backstackVisible: false,
|
||||||
})
|
} )
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// DATA HANDLERS
|
// DATA HANDLERS
|
||||||
addRecipe(mealType) {
|
addRecipe( mealType ) {
|
||||||
let filteredRecipes = this.recipes.filter((e) =>
|
let filteredRecipes = this.recipes.filter( ( e ) =>
|
||||||
this.getRecipes[mealType]
|
this.getRecipes[ mealType ] ?
|
||||||
? !this.getRecipes[mealType].includes(e.id)
|
!this.getRecipes[ mealType ].includes( e.id ) :
|
||||||
: true
|
true
|
||||||
)
|
)
|
||||||
this.$showModal(ActionDialogWithSearch, {
|
this.$showModal( ActionDialogWithSearch, {
|
||||||
props: {
|
props: {
|
||||||
title: "Select a recipe",
|
title: "Select a recipe",
|
||||||
recipes: filteredRecipes,
|
recipes: filteredRecipes,
|
||||||
},
|
},
|
||||||
}).then((recipeID) => {
|
} ).then( ( recipeID ) => {
|
||||||
recipeID && this.newEvent(recipeID, mealType)
|
recipeID && this.newEvent( recipeID, mealType )
|
||||||
})
|
} )
|
||||||
},
|
},
|
||||||
removeRecipeConfirm(mealType) {
|
removeRecipeConfirm( mealType ) {
|
||||||
return this.$showModal(ConfirmDialog, {
|
return this.$showModal( ConfirmDialog, {
|
||||||
props: {
|
props: {
|
||||||
title: `Remove recipe from ${mealType}`,
|
title: `Remove recipe from ${mealType}`,
|
||||||
cancelButtonText: "CANCEL",
|
cancelButtonText: "CANCEL",
|
||||||
okButtonText: "REMOVE",
|
okButtonText: "REMOVE",
|
||||||
},
|
},
|
||||||
})
|
} )
|
||||||
},
|
},
|
||||||
removeRecipe(mealType, recipeID) {
|
removeRecipe( mealType, recipeID ) {
|
||||||
let startHour = {
|
let startHour = {
|
||||||
breakfast: 0,
|
breakfast: 0,
|
||||||
lunch: 5,
|
lunch: 5,
|
||||||
dinner: 10,
|
dinner: 10,
|
||||||
snacks: 15,
|
snacks: 15,
|
||||||
}
|
}
|
||||||
this.removeRecipeConfirm(mealType).then((res) => {
|
this.removeRecipeConfirm( mealType ).then( ( res ) => {
|
||||||
if (res) {
|
if ( res ) {
|
||||||
let actualMealPlan = this.selectedDayMealPlans.filter(
|
let actualMealPlan = this.selectedDayMealPlans.filter(
|
||||||
(e) =>
|
( e ) =>
|
||||||
e.startDate.getHours() === startHour[mealType] &&
|
e.startDate.getHours() === startHour[ mealType ] &&
|
||||||
e.title === recipeID
|
e.title === recipeID
|
||||||
)[0]
|
)[ 0 ]
|
||||||
let mealPlan = {
|
let mealPlan = {
|
||||||
title: actualMealPlan.title,
|
title: actualMealPlan.title,
|
||||||
startDate: actualMealPlan.startDate,
|
startDate: actualMealPlan.startDate,
|
||||||
}
|
}
|
||||||
this.deleteMealPlanAction(mealPlan)
|
this.deleteMealPlanAction( mealPlan )
|
||||||
this.updateSelectedDatePlans()
|
this.updateSelectedDatePlans()
|
||||||
}
|
}
|
||||||
})
|
} )
|
||||||
},
|
},
|
||||||
|
|
||||||
// CALENDAR
|
// CALENDAR
|
||||||
updateSelectedDatePlans() {
|
updateSelectedDatePlans() {
|
||||||
let date = new Date(this.selectedDate)
|
let date = new Date( this.selectedDate )
|
||||||
setTimeout(() => {
|
setTimeout( () => {
|
||||||
this.selectedDayMealPlans = this.$refs.calendar.nativeView.getEventsForDate(
|
this.selectedDayMealPlans = this.$refs.calendar.nativeView.getEventsForDate(
|
||||||
date
|
date
|
||||||
)
|
)
|
||||||
}, 100)
|
}, 100 )
|
||||||
},
|
},
|
||||||
onDateSelected(args) {
|
onDateSelected( args ) {
|
||||||
this.selectedDate = args.date
|
this.selectedDate = args.date
|
||||||
this.selectedDayMealPlans = args.object.getEventsForDate(args.date)
|
this.selectedDayMealPlans = args.object.getEventsForDate( args.date )
|
||||||
},
|
},
|
||||||
newEvent(recipeID, mealType) {
|
newEvent( recipeID, mealType ) {
|
||||||
let date = new Date(this.selectedDate)
|
let date = new Date( this.selectedDate )
|
||||||
const selectedDate = () => {
|
const selectedDate = () => {
|
||||||
return {
|
return {
|
||||||
y: date.getFullYear(),
|
y: date.getFullYear(),
|
||||||
|
@ -426,45 +388,52 @@ export default {
|
||||||
d: date.getDate(),
|
d: date.getDate(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let { y, m, d } = selectedDate()
|
let {
|
||||||
|
y,
|
||||||
|
m,
|
||||||
|
d
|
||||||
|
} = selectedDate()
|
||||||
let mealTime = {
|
let mealTime = {
|
||||||
breakfast: {
|
breakfast: {
|
||||||
start: new Date(y, m, d, 0),
|
start: new Date( y, m, d, 0 ),
|
||||||
end: new Date(y, m, d, 4),
|
end: new Date( y, m, d, 4 ),
|
||||||
},
|
},
|
||||||
lunch: {
|
lunch: {
|
||||||
start: new Date(y, m, d, 5),
|
start: new Date( y, m, d, 5 ),
|
||||||
end: new Date(y, m, d, 9),
|
end: new Date( y, m, d, 9 ),
|
||||||
},
|
},
|
||||||
dinner: {
|
dinner: {
|
||||||
start: new Date(y, m, d, 10),
|
start: new Date( y, m, d, 10 ),
|
||||||
end: new Date(y, m, d, 14),
|
end: new Date( y, m, d, 14 ),
|
||||||
},
|
},
|
||||||
snacks: {
|
snacks: {
|
||||||
start: new Date(y, m, d, 15),
|
start: new Date( y, m, d, 15 ),
|
||||||
end: new Date(y, m, d, 19),
|
end: new Date( y, m, d, 19 ),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
let event = new CalendarEvent(
|
let event = new CalendarEvent(
|
||||||
recipeID,
|
recipeID,
|
||||||
mealTime[mealType].start,
|
mealTime[ mealType ].start,
|
||||||
mealTime[mealType].end,
|
mealTime[ mealType ].end,
|
||||||
false,
|
false,
|
||||||
new Color(this.color[mealType])
|
new Color( this.color[ mealType ] )
|
||||||
)
|
)
|
||||||
this.addMealPlanAction({ event, eventColor: this.color[mealType] })
|
this.addMealPlanAction( {
|
||||||
|
event,
|
||||||
|
eventColor: this.color[ mealType ]
|
||||||
|
} )
|
||||||
this.updateSelectedDatePlans()
|
this.updateSelectedDatePlans()
|
||||||
},
|
},
|
||||||
goToToday() {
|
goToToday() {
|
||||||
const date = new Date()
|
const date = new Date()
|
||||||
this.$refs.calendar.goToDate(date)
|
this.$refs.calendar.goToDate( date )
|
||||||
this.$refs.calendar.nativeView.selectedDate = date
|
this.$refs.calendar.nativeView.selectedDate = date
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.appTheme = ApplicationSettings.getString("appTheme", "Light")
|
this.appTheme = ApplicationSettings.getString( "appTheme", "Light" )
|
||||||
let d = new Date()
|
let d = new Date()
|
||||||
d.setHours(0, 0, 0)
|
d.setHours( 0, 0, 0 )
|
||||||
this.selectedDate = d
|
this.selectedDate = d
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,73 +1,55 @@
|
||||||
<template>
|
<template>
|
||||||
<Page @loaded="onPageLoad">
|
<Page @loaded="onPageLoad">
|
||||||
<ActionBar :androidElevation="viewIsScrolled ? 4 : 0">
|
<ActionBar :androidElevation="viewIsScrolled ? 4 : 0">
|
||||||
<GridLayout rows="*" columns="auto, *">
|
<GridLayout rows="*" columns="auto, *">
|
||||||
<MDButton
|
<MDButton class="bx left" variant="text" :text="icon.menu" automationText="Back" @tap="showDrawer" col="0" />
|
||||||
class="bx left"
|
<Label class="title orkm" :text="'Settings' | L" col="1" />
|
||||||
variant="text"
|
|
||||||
:text="icon.menu"
|
|
||||||
automationText="Back"
|
|
||||||
@tap="showDrawer"
|
|
||||||
col="0"
|
|
||||||
/>
|
|
||||||
<Label class="title orkm" text="Settings" col="1" />
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</ActionBar>
|
</ActionBar>
|
||||||
<ScrollView @scroll="onScroll">
|
<ScrollView @scroll="onScroll">
|
||||||
<StackLayout class="main-container">
|
<StackLayout class="main-container">
|
||||||
<Label text="Interface" class="group-header orkm" />
|
<Label :text="'Interface' | L" class="group-header orkm" />
|
||||||
|
<GridLayout columns="auto, *" class="option">
|
||||||
|
<MDRipple colSpan="2" @tap="selectAppLanguage" />
|
||||||
|
<Label col="0" verticalAlignment="center" class="bx" :text="icon.globe" />
|
||||||
|
<StackLayout col="1">
|
||||||
|
<Label :text="'App language' | L" />
|
||||||
|
<Label :text="appLanguage" class="info" />
|
||||||
|
</StackLayout>
|
||||||
|
</GridLayout>
|
||||||
<GridLayout columns="auto, *" class="option">
|
<GridLayout columns="auto, *" class="option">
|
||||||
<MDRipple colSpan="2" @tap="selectThemes" />
|
<MDRipple colSpan="2" @tap="selectThemes" />
|
||||||
<Label
|
<Label col="0" verticalAlignment="center" class="bx" :text="icon.theme" />
|
||||||
col="0"
|
|
||||||
verticalAlignment="center"
|
|
||||||
class="bx"
|
|
||||||
:text="icon.theme"
|
|
||||||
/>
|
|
||||||
<StackLayout col="1">
|
<StackLayout col="1">
|
||||||
<Label text="Theme" />
|
<Label :text="'Theme' | L" />
|
||||||
<Label :text="appTheme" class="info" />
|
<Label :text="`${appTheme}` | L" class="info" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<StackLayout class="hr m-10"></StackLayout>
|
<StackLayout class="hr m-10"></StackLayout>
|
||||||
<Label text="Database" class="group-header orkm" />
|
<Label :text="'Database' | L" class="group-header orkm" />
|
||||||
<GridLayout columns="auto, *" class="option">
|
<GridLayout columns="auto, *" class="option">
|
||||||
<!-- <MDRipple colSpan="2" @tap="folderPicker" /> -->
|
|
||||||
<MDRipple colSpan="2" @tap="exportCheck" />
|
<MDRipple colSpan="2" @tap="exportCheck" />
|
||||||
<Label col="0" class="bx" :text="icon.export" />
|
<Label col="0" class="bx" :text="icon.export" />
|
||||||
<StackLayout col="1">
|
<StackLayout col="1">
|
||||||
<Label text="Export a full backup" />
|
<Label :text="'Export a full backup' | L" textWrap="true" />
|
||||||
<Label
|
<Label v-if="!backupInProgress" :text="'Generates a zip file that contains all your data. This file can be imported back.' | L" class="info" textWrap="true" />
|
||||||
v-if="!backupInProgress"
|
|
||||||
text="Generates a zip file that contains all your data. This file can be imported back."
|
|
||||||
class="info"
|
|
||||||
textWrap="true"
|
|
||||||
/>
|
|
||||||
<GridLayout class="progressContainer" v-else columns="*, 64">
|
<GridLayout class="progressContainer" v-else columns="*, 64">
|
||||||
<MDProgress
|
<MDProgress col="0" :value="backupProgress" maxValue="100"></MDProgress>
|
||||||
col="0"
|
|
||||||
:value="backupProgress"
|
|
||||||
maxValue="100"
|
|
||||||
></MDProgress>
|
|
||||||
<Label col="1" :text="` ${backupProgress}%`" />
|
<Label col="1" :text="` ${backupProgress}%`" />
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<GridLayout columns="auto, *" class="option"
|
<GridLayout columns="auto, *" class="option">
|
||||||
><MDRipple colSpan="2" @tap="importCheck" />
|
<MDRipple colSpan="2" @tap="importCheck" />
|
||||||
<Label col="0" class="bx" :text="icon.import" />
|
<Label col="0" class="bx" :text="icon.import" />
|
||||||
<StackLayout col="1">
|
<StackLayout col="1">
|
||||||
<Label text="Import from backup" />
|
<Label :text="'Import from backup' | L" textWrap="true" />
|
||||||
<Label
|
<Label :text="'Supports full backups exported by this app' | L" class="info" textWrap="true" />
|
||||||
text="Supports full backups exported by this app"
|
|
||||||
class="info"
|
|
||||||
textWrap="true"
|
|
||||||
/>
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -77,13 +59,28 @@ import {
|
||||||
knownFolders,
|
knownFolders,
|
||||||
File,
|
File,
|
||||||
Folder,
|
Folder,
|
||||||
} from "@nativescript/core"
|
Observable,
|
||||||
|
Device
|
||||||
|
}
|
||||||
|
from "@nativescript/core"
|
||||||
import * as Permissions from "@nativescript-community/perms"
|
import * as Permissions from "@nativescript-community/perms"
|
||||||
import { Zip } from "@nativescript/zip"
|
import {
|
||||||
|
Zip
|
||||||
|
}
|
||||||
|
from "@nativescript/zip"
|
||||||
import * as Toast from "nativescript-toast"
|
import * as Toast from "nativescript-toast"
|
||||||
import * as Filepicker from "nativescript-plugin-filepicker"
|
import * as Filepicker from "nativescript-plugin-filepicker"
|
||||||
import Theme from "@nativescript/theme"
|
import Theme from "@nativescript/theme"
|
||||||
import { mapState, mapActions } from "vuex"
|
import {
|
||||||
|
localize,
|
||||||
|
overrideLocale
|
||||||
|
}
|
||||||
|
from "@nativescript/localize"
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions
|
||||||
|
}
|
||||||
|
from "vuex"
|
||||||
|
|
||||||
import ActionDialog from "./modal/ActionDialog.vue"
|
import ActionDialog from "./modal/ActionDialog.vue"
|
||||||
import ConfirmDialog from "./modal/ConfirmDialog.vue"
|
import ConfirmDialog from "./modal/ConfirmDialog.vue"
|
||||||
|
@ -95,145 +92,182 @@ export default {
|
||||||
return {
|
return {
|
||||||
viewIsScrolled: false,
|
viewIsScrolled: false,
|
||||||
appTheme: "Light",
|
appTheme: "Light",
|
||||||
|
appLanguage: "English",
|
||||||
backupProgress: 0,
|
backupProgress: 0,
|
||||||
backupInProgress: false,
|
backupInProgress: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState([
|
...mapState( [
|
||||||
"icon",
|
"icon",
|
||||||
"recipes",
|
"recipes",
|
||||||
"userCategories",
|
"userCategories",
|
||||||
"userYieldUnits",
|
"userYieldUnits",
|
||||||
"mealPlans",
|
"mealPlans",
|
||||||
"currentComponent",
|
"currentComponent",
|
||||||
]),
|
"language",
|
||||||
|
] ),
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions([
|
...mapActions( [
|
||||||
"setCurrentComponentAction",
|
"setCurrentComponentAction",
|
||||||
"importCategoriesAction",
|
"importCategoriesAction",
|
||||||
"importYieldUnitsAction",
|
"importYieldUnitsAction",
|
||||||
"importRecipesAction",
|
"importRecipesAction",
|
||||||
"importMealPlansAction",
|
"importMealPlansAction",
|
||||||
]),
|
] ),
|
||||||
onPageLoad() {
|
onPageLoad( args ) {
|
||||||
this.setCurrentComponentAction("Settings")
|
const page = args.object;
|
||||||
|
page.bindingContext = new Observable();
|
||||||
|
this.setCurrentComponentAction( "Settings" )
|
||||||
},
|
},
|
||||||
// HELPERS
|
// HELPERS
|
||||||
showDrawer() {
|
showDrawer() {
|
||||||
utils.showDrawer()
|
utils.showDrawer()
|
||||||
},
|
},
|
||||||
onScroll(args) {
|
onScroll( args ) {
|
||||||
this.viewIsScrolled = args.scrollY ? true : false
|
this.viewIsScrolled = args.scrollY ? true : false
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// LANGUAGE SELECTION
|
||||||
|
selectAppLanguage() {
|
||||||
|
let languages = this.language.map( e => e.title )
|
||||||
|
this.$showModal( ActionDialog, {
|
||||||
|
props: {
|
||||||
|
title: "App language",
|
||||||
|
list: [ ...languages ],
|
||||||
|
},
|
||||||
|
} ).then( ( action ) => {
|
||||||
|
if ( action && action !== "Cancel" && this.appLanguage !== action ) {
|
||||||
|
let currentLocale = Device.language.split( '-' )[ 0 ]
|
||||||
|
let locale = this.language.filter( e => e.title === action )[ 0 ].locale
|
||||||
|
if ( currentLocale !== locale ) {
|
||||||
|
this.$showModal( ConfirmDialog, {
|
||||||
|
props: {
|
||||||
|
title: "Restart required",
|
||||||
|
description: localize( "EnRecipes needs to be restarted for the app language to take effect." ),
|
||||||
|
cancelButtonText: "CANCEL",
|
||||||
|
okButtonText: "RESTART",
|
||||||
|
},
|
||||||
|
} ).then( ( result ) => {
|
||||||
|
if ( result ) {
|
||||||
|
this.appLanguage = action
|
||||||
|
ApplicationSettings.setString( "appLanguage", action )
|
||||||
|
|
||||||
|
overrideLocale( locale )
|
||||||
|
setTimeout( ( e ) => utils.restartApp(), 250 )
|
||||||
|
}
|
||||||
|
} )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} )
|
||||||
|
},
|
||||||
// THEME SELECTION
|
// THEME SELECTION
|
||||||
selectThemes() {
|
selectThemes() {
|
||||||
this.$showModal(ActionDialog, {
|
this.$showModal( ActionDialog, {
|
||||||
props: {
|
props: {
|
||||||
title: "Theme",
|
title: "Theme",
|
||||||
list: ["Light", "Dark"],
|
list: [ "Light", "Dark" ],
|
||||||
height: "96",
|
height: "96",
|
||||||
},
|
},
|
||||||
}).then((action) => {
|
} ).then( ( action ) => {
|
||||||
if (action && action !== "Cancel" && this.appTheme !== action) {
|
if ( action && action !== "Cancel" && this.appTheme !== action ) {
|
||||||
this.$showModal(ConfirmDialog, {
|
this.$showModal( ConfirmDialog, {
|
||||||
props: {
|
props: {
|
||||||
title: "Reload required",
|
title: "Restart required",
|
||||||
description:
|
description: localize( "EnRecipes needs to be restarted for the theme change to take effect." ),
|
||||||
"EnRecipes needs to be reloaded for the theme change to take effect.",
|
|
||||||
cancelButtonText: "CANCEL",
|
cancelButtonText: "CANCEL",
|
||||||
okButtonText: "RELOAD",
|
okButtonText: "RESTART",
|
||||||
},
|
},
|
||||||
}).then((result) => {
|
} ).then( ( result ) => {
|
||||||
if (result) {
|
if ( result ) {
|
||||||
this.appTheme = action
|
this.appTheme = action
|
||||||
ApplicationSettings.setString("appTheme", action)
|
ApplicationSettings.setString( "appTheme", action )
|
||||||
setTimeout((e) => utils.restartApp(), 250)
|
setTimeout( ( e ) => utils.restartApp(), 250 )
|
||||||
}
|
}
|
||||||
})
|
} )
|
||||||
}
|
}
|
||||||
})
|
} )
|
||||||
},
|
},
|
||||||
|
|
||||||
// EXPORT HANDLERS
|
// EXPORT HANDLERS
|
||||||
exportCheck() {
|
exportCheck() {
|
||||||
if (!this.recipes.length) {
|
if ( !this.recipes.length ) {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
"Add at least one recipe to perform a backup",
|
localize( "Add at least one recipe to perform a backup" ),
|
||||||
"long"
|
"long"
|
||||||
).show()
|
).show()
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
this.permissionCheck(
|
this.permissionCheck(
|
||||||
this.permissionConfirmation,
|
this.permissionConfirmation,
|
||||||
"EnRecipes requires storage permission in order to backup your data to this device.",
|
localize( "EnRecipes requires storage permission in order to backup your data to this device." ),
|
||||||
this.exportBackup
|
this.exportBackup
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
exportBackup() {
|
exportBackup() {
|
||||||
this.exportFiles("create")
|
this.exportFiles( "create" )
|
||||||
let date = new Date()
|
let date = new Date()
|
||||||
let formattedDate =
|
let formattedDate =
|
||||||
date.getFullYear() +
|
date.getFullYear() +
|
||||||
"-" +
|
"-" +
|
||||||
("0" + (date.getMonth() + 1)).slice(-2) +
|
( "0" + ( date.getMonth() + 1 ) ).slice( -2 ) +
|
||||||
"-" +
|
"-" +
|
||||||
("0" + date.getDate()).slice(-2) +
|
( "0" + date.getDate() ).slice( -2 ) +
|
||||||
"_" +
|
"_" +
|
||||||
("0" + date.getHours()).slice(-2) +
|
( "0" + date.getHours() ).slice( -2 ) +
|
||||||
("0" + date.getMinutes()).slice(-2) +
|
( "0" + date.getMinutes() ).slice( -2 ) +
|
||||||
("0" + date.getSeconds()).slice(-2)
|
( "0" + date.getSeconds() ).slice( -2 )
|
||||||
const sdDownloadPath = Folder.fromPath(
|
const sdDownloadPath = Folder.fromPath(
|
||||||
android.os.Environment.getExternalStorageDirectory().getAbsolutePath()
|
android.os.Environment.getExternalStorageDirectory().getAbsolutePath()
|
||||||
).getFolder("Download").path
|
).getFolder( "Download" ).path
|
||||||
let fromPath = path.join(knownFolders.documents().path, "EnRecipes")
|
let fromPath = path.join( knownFolders.documents().path, "EnRecipes" )
|
||||||
let destPath = path.join(
|
let destPath = path.join(
|
||||||
sdDownloadPath,
|
sdDownloadPath,
|
||||||
`EnRecipes-Backup_${formattedDate}.zip`
|
`EnRecipes-Backup_${formattedDate}.zip`
|
||||||
)
|
)
|
||||||
this.backupInProgress = true
|
this.backupInProgress = true
|
||||||
Zip.zip({
|
Zip.zip( {
|
||||||
directory: fromPath,
|
directory: fromPath,
|
||||||
archive: destPath,
|
archive: destPath,
|
||||||
onProgress: (progress) => {
|
onProgress: ( progress ) => {
|
||||||
this.backupProgress = progress
|
this.backupProgress = progress
|
||||||
},
|
},
|
||||||
}).then((success) => {
|
} ).then( ( success ) => {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
"Backup file successfully saved to Download folder",
|
"Backup file successfully saved to Download folder",
|
||||||
"long"
|
"long"
|
||||||
).show()
|
).show()
|
||||||
this.exportFiles("delete")
|
this.exportFiles( "delete" )
|
||||||
})
|
} )
|
||||||
},
|
},
|
||||||
exportFiles(option) {
|
exportFiles( option ) {
|
||||||
const folder = path.join(knownFolders.documents().path, "EnRecipes")
|
const folder = path.join( knownFolders.documents().path, "EnRecipes" )
|
||||||
const EnRecipesFile = File.fromPath(path.join(folder, "recipes.json"))
|
const EnRecipesFile = File.fromPath( path.join( folder, "recipes.json" ) )
|
||||||
let userCategoriesFile, userYieldUnitsFile, mealPlansFile
|
let userCategoriesFile, userYieldUnitsFile, mealPlansFile
|
||||||
if (this.userCategories.length) {
|
if ( this.userCategories.length ) {
|
||||||
userCategoriesFile = File.fromPath(
|
userCategoriesFile = File.fromPath(
|
||||||
path.join(folder, "userCategories.json")
|
path.join( folder, "userCategories.json" )
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (this.userYieldUnits.length) {
|
if ( this.userYieldUnits.length ) {
|
||||||
userYieldUnitsFile = File.fromPath(
|
userYieldUnitsFile = File.fromPath(
|
||||||
path.join(folder, "userYieldUnits.json")
|
path.join( folder, "userYieldUnits.json" )
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (this.mealPlans.length) {
|
if ( this.mealPlans.length ) {
|
||||||
mealPlansFile = File.fromPath(path.join(folder, "mealPlans.json"))
|
mealPlansFile = File.fromPath( path.join( folder, "mealPlans.json" ) )
|
||||||
}
|
}
|
||||||
switch (option) {
|
switch ( option ) {
|
||||||
case "create":
|
case "create":
|
||||||
this.writeDataToFile(EnRecipesFile, this.recipes)
|
this.writeDataToFile( EnRecipesFile, this.recipes )
|
||||||
this.userCategories.length &&
|
this.userCategories.length &&
|
||||||
this.writeDataToFile(userCategoriesFile, this.userCategories)
|
this.writeDataToFile( userCategoriesFile, this.userCategories )
|
||||||
this.userYieldUnits.length &&
|
this.userYieldUnits.length &&
|
||||||
this.writeDataToFile(userYieldUnitsFile, this.userYieldUnits)
|
this.writeDataToFile( userYieldUnitsFile, this.userYieldUnits )
|
||||||
this.mealPlans.length &&
|
this.mealPlans.length &&
|
||||||
this.writeDataToFile(mealPlansFile, this.mealPlans)
|
this.writeDataToFile( mealPlansFile, this.mealPlans )
|
||||||
break
|
break
|
||||||
case "delete":
|
case "delete":
|
||||||
EnRecipesFile.remove()
|
EnRecipesFile.remove()
|
||||||
|
@ -245,144 +279,159 @@ export default {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
writeDataToFile(file, data) {
|
writeDataToFile( file, data ) {
|
||||||
file.writeText(JSON.stringify(data))
|
file.writeText( JSON.stringify( data ) )
|
||||||
},
|
},
|
||||||
|
|
||||||
// IMPORT HANDLERS
|
// IMPORT HANDLERS
|
||||||
importCheck() {
|
importCheck() {
|
||||||
this.permissionCheck(
|
this.permissionCheck(
|
||||||
this.permissionConfirmation,
|
this.permissionConfirmation,
|
||||||
"EnRecipes requires storage permission in order to import your data from a previous backup.",
|
localize( "EnRecipes requires storage permission in order to import your data from a previous backup." ),
|
||||||
this.openFilePicker
|
this.openFilePicker
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
openFilePicker() {
|
openFilePicker() {
|
||||||
Filepicker.create({
|
Filepicker.create( {
|
||||||
mode: "single",
|
mode: "single",
|
||||||
extensions: ["zip"],
|
extensions: [ "zip" ],
|
||||||
})
|
} )
|
||||||
.present()
|
.present()
|
||||||
.then((selection) => {
|
.then( ( selection ) => {
|
||||||
Toast.makeText("Processing...").show()
|
Toast.makeText( localize( "Verifying..." ) ).show()
|
||||||
let zipPath = selection[0]
|
let zipPath = selection[ 0 ]
|
||||||
this.validateZipContent(zipPath)
|
this.validateZipContent( zipPath )
|
||||||
})
|
} )
|
||||||
},
|
},
|
||||||
importDataToDB(data, db, zipPath) {
|
importDataToDB( data, db, zipPath ) {
|
||||||
switch (db) {
|
switch ( db ) {
|
||||||
case "EnRecipesDB":
|
case "EnRecipesDB":
|
||||||
this.importImages(zipPath)
|
this.importImages( zipPath )
|
||||||
this.importRecipesAction(data)
|
this.importRecipesAction( data )
|
||||||
break
|
break
|
||||||
case "userCategoriesDB":
|
case "userCategoriesDB":
|
||||||
this.importCategoriesAction(data)
|
this.importCategoriesAction( data )
|
||||||
break
|
break
|
||||||
case "userYieldUnitsDB":
|
case "userYieldUnitsDB":
|
||||||
this.importYieldUnitsAction(data)
|
this.importYieldUnitsAction( data )
|
||||||
break
|
break
|
||||||
case "mealPlansDB":
|
case "mealPlansDB":
|
||||||
this.importMealPlansAction(data)
|
this.importMealPlansAction( data )
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
isFileDataValid(file) {
|
isFileDataValid( file ) {
|
||||||
file.forEach((file, i) => {
|
file.forEach( ( file, i ) => {
|
||||||
if (File.exists(file.path)) {
|
if ( File.exists( file.path ) ) {
|
||||||
File.fromPath(file.path)
|
File.fromPath( file.path )
|
||||||
.readText()
|
.readText()
|
||||||
.then((data) => {
|
.then( ( data ) => {
|
||||||
Array.isArray(JSON.parse(data)) &&
|
Array.isArray( JSON.parse( data ) ) &&
|
||||||
this.importDataToDB(JSON.parse(data), file.db, file.zipPath)
|
this.importDataToDB( JSON.parse( data ), file.db, file.zipPath )
|
||||||
})
|
} )
|
||||||
}
|
}
|
||||||
})
|
} )
|
||||||
},
|
},
|
||||||
validateZipContent(zipPath) {
|
validateZipContent( zipPath ) {
|
||||||
Zip.unzip({
|
Zip.unzip( {
|
||||||
archive: zipPath,
|
archive: zipPath,
|
||||||
overwrite: true,
|
overwrite: true,
|
||||||
}).then((extractedFolderPath) => {
|
} ).then( ( extractedFolderPath ) => {
|
||||||
let cacheFolderPath = extractedFolderPath + "/EnRecipes"
|
let cacheFolderPath = extractedFolderPath + "/EnRecipes"
|
||||||
const EnRecipesFilePath = cacheFolderPath + "/recipes.json"
|
const EnRecipesFilePath = cacheFolderPath + "/recipes.json"
|
||||||
const userCategoriesFilePath = cacheFolderPath + "/userCategories.json"
|
const userCategoriesFilePath = cacheFolderPath + "/userCategories.json"
|
||||||
const userYieldUnitsFilePath = cacheFolderPath + "/userYieldUnits.json"
|
const userYieldUnitsFilePath = cacheFolderPath + "/userYieldUnits.json"
|
||||||
const mealPlansFilePath = cacheFolderPath + "/mealPlans.json"
|
const mealPlansFilePath = cacheFolderPath + "/mealPlans.json"
|
||||||
if (Folder.exists(cacheFolderPath)) {
|
if ( Folder.exists( cacheFolderPath ) ) {
|
||||||
this.isFileDataValid([
|
this.isFileDataValid( [ {
|
||||||
{
|
|
||||||
zipPath,
|
zipPath,
|
||||||
path: EnRecipesFilePath,
|
path: EnRecipesFilePath,
|
||||||
db: "EnRecipesDB",
|
db: "EnRecipesDB",
|
||||||
},
|
},
|
||||||
{ zipPath, path: userCategoriesFilePath, db: "userCategoriesDB" },
|
{
|
||||||
{ zipPath, path: userYieldUnitsFilePath, db: "userYieldUnitsDB" },
|
zipPath,
|
||||||
{ zipPath, path: mealPlansFilePath, db: "mealPlansDB" },
|
path: userCategoriesFilePath,
|
||||||
])
|
db: "userCategoriesDB"
|
||||||
} else {
|
},
|
||||||
Folder.fromPath(extractedFolderPath).remove()
|
{
|
||||||
|
zipPath,
|
||||||
|
path: userYieldUnitsFilePath,
|
||||||
|
db: "userYieldUnitsDB"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
zipPath,
|
||||||
|
path: mealPlansFilePath,
|
||||||
|
db: "mealPlansDB"
|
||||||
|
},
|
||||||
|
] )
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Folder.fromPath( extractedFolderPath ).remove()
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
"Import failed. Backup file is incorrect or corrupt",
|
"Import failed. Backup file is incorrect or corrupt",
|
||||||
"long"
|
"long"
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
if (Folder.exists(cacheFolderPath + "/Images")) {
|
if ( Folder.exists( cacheFolderPath + "/Images" ) ) {
|
||||||
this.importImages(cacheFolderPath + "/Images")
|
this.importImages( cacheFolderPath + "/Images" )
|
||||||
}
|
}
|
||||||
})
|
} )
|
||||||
},
|
},
|
||||||
importImages(sourcePath) {
|
importImages( sourcePath ) {
|
||||||
let dest = knownFolders.documents().path
|
let dest = knownFolders.documents().path
|
||||||
Zip.unzip({
|
Zip.unzip( {
|
||||||
archive: sourcePath,
|
archive: sourcePath,
|
||||||
directory: dest,
|
directory: dest,
|
||||||
overwrite: true,
|
overwrite: true,
|
||||||
}).then((res) => {
|
} ).then( ( res ) => {
|
||||||
Toast.makeText("Import successful", "long").show()
|
Toast.makeText( localize( "Import successful" ), "long" ).show()
|
||||||
this.$navigateBack()
|
this.$navigateBack()
|
||||||
})
|
} )
|
||||||
},
|
},
|
||||||
|
|
||||||
// PERMISSIONS HANDLER
|
// PERMISSIONS HANDLER
|
||||||
permissionCheck(confirmation, description, action) {
|
permissionCheck( confirmation, description, action ) {
|
||||||
if (!ApplicationSettings.getBoolean("storagePermissionAsked", false)) {
|
if ( !ApplicationSettings.getBoolean( "storagePermissionAsked", false ) ) {
|
||||||
confirmation(description).then((e) => {
|
confirmation( description ).then( ( e ) => {
|
||||||
if (e) {
|
if ( e ) {
|
||||||
Permissions.request("photo").then((res) => {
|
Permissions.request( "photo" ).then( ( res ) => {
|
||||||
let status = res[Object.keys(res)[0]]
|
let status = res[ Object.keys( res )[ 0 ] ]
|
||||||
if (status === "authorized") action()
|
if ( status === "authorized" ) action()
|
||||||
if (status !== "denied")
|
if ( status !== "denied" )
|
||||||
ApplicationSettings.setBoolean("storagePermissionAsked", true)
|
ApplicationSettings.setBoolean( "storagePermissionAsked", true )
|
||||||
else Toast.makeText("Permission denied").show()
|
else Toast.makeText( localize( "Permission denied" ) ).show()
|
||||||
})
|
} )
|
||||||
}
|
}
|
||||||
})
|
} )
|
||||||
} else {
|
}
|
||||||
Permissions.check("photo").then((res) => {
|
else {
|
||||||
let status = res[Object.keys(res)[0]]
|
Permissions.check( "photo" ).then( ( res ) => {
|
||||||
if (status !== "authorized") {
|
let status = res[ Object.keys( res )[ 0 ] ]
|
||||||
confirmation(description).then((e) => {
|
if ( status !== "authorized" ) {
|
||||||
|
confirmation( description ).then( ( e ) => {
|
||||||
e && utils.openAppSettingsPage()
|
e && utils.openAppSettingsPage()
|
||||||
})
|
} )
|
||||||
} else action()
|
}
|
||||||
})
|
else action()
|
||||||
|
} )
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
permissionConfirmation(description) {
|
permissionConfirmation( description ) {
|
||||||
return this.$showModal(ConfirmDialog, {
|
return this.$showModal( ConfirmDialog, {
|
||||||
props: {
|
props: {
|
||||||
title: "Grant permission",
|
title: "Grant permission",
|
||||||
description,
|
description,
|
||||||
cancelButtonText: "NOT NOW",
|
cancelButtonText: "NOT NOW",
|
||||||
okButtonText: "CONTINUE",
|
okButtonText: "CONTINUE",
|
||||||
},
|
},
|
||||||
})
|
} )
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.appTheme = ApplicationSettings.getString("appTheme", "Light")
|
this.appTheme = ApplicationSettings.getString( "appTheme", "Light" )
|
||||||
|
this.appLanguage = ApplicationSettings.getString( "appLanguage", localize( "System default" ) )
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,217 +1,92 @@
|
||||||
<template>
|
<template>
|
||||||
<Page @loaded="onPageLoad" @unloaded="onPageUnload">
|
<Page @loaded="onPageLoad" @unloaded="onPageUnload">
|
||||||
<ActionBar flat="true">
|
<ActionBar flat="true">
|
||||||
<GridLayout rows="48" columns="auto, *, auto">
|
<GridLayout rows="48" columns="auto, *, auto">
|
||||||
<MDButton
|
<MDButton variant="text" row="0" col="0" class="bx" :text="icon.back" automationText="Back" @tap="$navigateBack()" />
|
||||||
variant="text"
|
|
||||||
row="0"
|
|
||||||
col="0"
|
|
||||||
class="bx"
|
|
||||||
:text="icon.back"
|
|
||||||
automationText="Back"
|
|
||||||
@tap="$navigateBack()"
|
|
||||||
/>
|
|
||||||
<!-- <ScrollView
|
|
||||||
row="1"
|
|
||||||
col="0"
|
|
||||||
colSpan="3"
|
|
||||||
orientation="horizontal"
|
|
||||||
scrollBarIndicatorVisible="false"
|
|
||||||
>
|
|
||||||
<Label
|
|
||||||
class="title orkm"
|
|
||||||
:text="recipe.title"
|
|
||||||
verticalAlignment="bottom"
|
|
||||||
/>
|
|
||||||
</ScrollView> -->
|
|
||||||
<FlexboxLayout row="0" col="2" alignItems="center">
|
<FlexboxLayout row="0" col="2" alignItems="center">
|
||||||
<MDButton
|
<MDButton v-if="!filterTrylater" variant="text" class="bx" :text="recipe.tried ? icon.trylaterOutline : icon.trylater" @tap="toggleTrylater" />
|
||||||
v-if="!filterTrylater"
|
<MDButton v-else variant="text" class="bx" :text="icon.check" @tap="recipeTried" />
|
||||||
variant="text"
|
<MDButton variant="text" class="bx" :text="recipe.isFavorite ? icon.heart : icon.heartOutline" @tap="toggleFavourite" />
|
||||||
class="bx"
|
<MDButton variant="text" v-if="!busy" class="bx" :text="icon.edit" @tap="editRecipe" />
|
||||||
:text="recipe.tried ? icon.trylaterOutline : icon.trylater"
|
|
||||||
@tap="toggleTrylater"
|
|
||||||
/>
|
|
||||||
<MDButton
|
|
||||||
v-else
|
|
||||||
variant="text"
|
|
||||||
class="bx"
|
|
||||||
:text="icon.check"
|
|
||||||
@tap="recipeTried"
|
|
||||||
/>
|
|
||||||
<MDButton
|
|
||||||
variant="text"
|
|
||||||
class="bx"
|
|
||||||
:text="recipe.isFavorite ? icon.heart : icon.heartOutline"
|
|
||||||
@tap="toggleFavorite"
|
|
||||||
/>
|
|
||||||
<MDButton
|
|
||||||
variant="text"
|
|
||||||
v-if="!busy"
|
|
||||||
class="bx"
|
|
||||||
:text="icon.edit"
|
|
||||||
@tap="editRecipe"
|
|
||||||
/>
|
|
||||||
<MDActivityIndicator v-else :busy="busy" />
|
<MDActivityIndicator v-else :busy="busy" />
|
||||||
</FlexboxLayout>
|
</FlexboxLayout>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</ActionBar>
|
</ActionBar>
|
||||||
<AbsoluteLayout>
|
<AbsoluteLayout>
|
||||||
<Tabs
|
<Tabs width="100%" height="100%" :selectedIndex="selectedTabIndex" @selectedIndexChange="selectedIndexChange" class="viewRecipe">
|
||||||
width="100%"
|
|
||||||
height="100%"
|
|
||||||
:selectedIndex="selectedTabIndex"
|
|
||||||
@selectedIndexChange="selectedIndexChange"
|
|
||||||
class="viewRecipe"
|
|
||||||
>
|
|
||||||
<TabStrip :androidElevation="viewIsScrolled ? 4 : 0">
|
<TabStrip :androidElevation="viewIsScrolled ? 4 : 0">
|
||||||
<TabStripItem>
|
<TabStripItem>
|
||||||
<Label text="Overview"></Label>
|
<Label :text="'Overview' | L"></Label>
|
||||||
</TabStripItem>
|
</TabStripItem>
|
||||||
<TabStripItem>
|
<TabStripItem>
|
||||||
<Label text="Ingredients"></Label>
|
<Label :text="'Ingredients' | L"></Label>
|
||||||
</TabStripItem>
|
</TabStripItem>
|
||||||
<TabStripItem>
|
<TabStripItem>
|
||||||
<Label text="Instructions"></Label>
|
<Label :text="'Instructions' | L"></Label>
|
||||||
</TabStripItem>
|
</TabStripItem>
|
||||||
<TabStripItem>
|
<TabStripItem>
|
||||||
<Label text="Combinations"></Label>
|
<Label :text="'Combinations' | L"></Label>
|
||||||
</TabStripItem>
|
</TabStripItem>
|
||||||
<TabStripItem>
|
<TabStripItem>
|
||||||
<Label text="Notes"></Label>
|
<Label :text="'Notes' | L"></Label>
|
||||||
</TabStripItem>
|
</TabStripItem>
|
||||||
</TabStrip>
|
</TabStrip>
|
||||||
|
|
||||||
<TabContentItem>
|
<TabContentItem>
|
||||||
<ScrollView @scroll="onScroll">
|
<ScrollView @scroll="onScroll">
|
||||||
<StackLayout>
|
<StackLayout>
|
||||||
<StackLayout
|
<StackLayout width="100%" :height="screenWidth" verticalAlignment="center" class="imageHolder">
|
||||||
width="100%"
|
<Image v-if="recipe.imageSrc" :src="recipe.imageSrc" stretch="aspectFill" width="100%" :height="screenWidth" />
|
||||||
:height="screenWidth"
|
<Label v-else horizontalAlignment="center" class="bx" fontSize="160" :text="icon.image" />
|
||||||
verticalAlignment="center"
|
|
||||||
class="imageHolder"
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
v-if="recipe.imageSrc"
|
|
||||||
:src="recipe.imageSrc"
|
|
||||||
stretch="aspectFill"
|
|
||||||
width="100%"
|
|
||||||
:height="screenWidth"
|
|
||||||
/>
|
|
||||||
<Label
|
|
||||||
v-else
|
|
||||||
horizontalAlignment="center"
|
|
||||||
class="bx"
|
|
||||||
fontSize="160"
|
|
||||||
:text="icon.image"
|
|
||||||
/>
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<StackLayout margin="16 8 80">
|
<StackLayout margin="16 8 80">
|
||||||
<Label class="category orkm" :text="recipe.category" />
|
<Label class="category orkm" :text="`${recipe.category}` | L" />
|
||||||
<Label
|
<Label margin="0 8" class="title orkm" :text="recipe.title" textWrap="true" />
|
||||||
margin="0 8"
|
<Label class="time" :text="`${$options.filters.L('Preparation time')}: ${formattedTime(recipe.prepTime)}`" textWrap="true" />
|
||||||
class="title orkm"
|
<Label class="time" :text="`${$options.filters.L('Cooking time')}: ${formattedTime(recipe.cookTime)}`" textWrap="true" />
|
||||||
:text="recipe.title"
|
<GridLayout rows="auto, auto" columns="*, *" class="overviewContainer">
|
||||||
textWrap="true"
|
<GridLayout class="overviewItem" row="0" col="0" rows="auto, auto" columns="*">
|
||||||
/>
|
|
||||||
<StackLayout orientation="horizontal" class="time">
|
|
||||||
<Label text="Preparation time:" />
|
|
||||||
<Label :text="` ${formattedTime(recipe.prepTime)}`" />
|
|
||||||
</StackLayout>
|
|
||||||
<StackLayout orientation="horizontal" class="time">
|
|
||||||
<Label text="Cooking time:" />
|
|
||||||
<Label :text="` ${formattedTime(recipe.cookTime)}`" />
|
|
||||||
</StackLayout>
|
|
||||||
<GridLayout
|
|
||||||
rows="auto, auto"
|
|
||||||
columns="*, *"
|
|
||||||
class="overviewContainer"
|
|
||||||
>
|
|
||||||
<GridLayout
|
|
||||||
class="overviewItem"
|
|
||||||
row="0"
|
|
||||||
col="0"
|
|
||||||
rows="auto, auto"
|
|
||||||
columns="*"
|
|
||||||
>
|
|
||||||
<MDRipple rowSpan="2" @tap="selectedTabIndex = 1" />
|
<MDRipple rowSpan="2" @tap="selectedTabIndex = 1" />
|
||||||
<Label row="0" class="bx" :text="icon.item" />
|
<Label row="0" class="bx" :text="icon.item" />
|
||||||
<Label
|
<Label row="1" class="itemCount" :text="
|
||||||
row="1"
|
|
||||||
class="itemCount"
|
|
||||||
:text="
|
|
||||||
`${recipe.ingredients.length} ${
|
`${recipe.ingredients.length} ${
|
||||||
recipe.ingredients.length == 1
|
recipe.ingredients.length == 1
|
||||||
? 'Ingredient'
|
? $options.filters.L('Ingredient')
|
||||||
: 'Ingredients'
|
: $options.filters.L('Ingredients')
|
||||||
}`
|
}`
|
||||||
"
|
" textWrap="true" />
|
||||||
textWrap="true"
|
|
||||||
/>
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<GridLayout
|
<GridLayout class="overviewItem" row="0" col="1" rows="auto, auto" columns="*">
|
||||||
class="overviewItem"
|
|
||||||
row="0"
|
|
||||||
col="1"
|
|
||||||
rows="auto, auto"
|
|
||||||
columns="*"
|
|
||||||
>
|
|
||||||
<MDRipple rowSpan="2" @tap="selectedTabIndex = 2" />
|
<MDRipple rowSpan="2" @tap="selectedTabIndex = 2" />
|
||||||
<Label row="0" class="bx" :text="icon.step" />
|
<Label row="0" class="bx" :text="icon.step" />
|
||||||
<Label
|
<Label row="1" class="itemCount" :text="
|
||||||
row="1"
|
|
||||||
class="itemCount"
|
|
||||||
:text="
|
|
||||||
`${recipe.instructions.length} ${
|
`${recipe.instructions.length} ${
|
||||||
recipe.instructions.length == 1
|
recipe.instructions.length == 1
|
||||||
? 'Instruction'
|
? $options.filters.L('Instruction')
|
||||||
: 'Instructions'
|
: $options.filters.L('Instructions')
|
||||||
}`
|
}`
|
||||||
"
|
" textWrap="true" />
|
||||||
textWrap="true"
|
|
||||||
/>
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<GridLayout
|
<GridLayout class="overviewItem" row="1" col="0" rows="auto, auto" columns="*">
|
||||||
class="overviewItem"
|
|
||||||
row="1"
|
|
||||||
col="0"
|
|
||||||
rows="auto, auto"
|
|
||||||
columns="*"
|
|
||||||
>
|
|
||||||
<MDRipple rowSpan="2" @tap="selectedTabIndex = 3" />
|
<MDRipple rowSpan="2" @tap="selectedTabIndex = 3" />
|
||||||
<Label row="0" class="bx" :text="icon.outline" />
|
<Label row="0" class="bx" :text="icon.outline" />
|
||||||
<Label
|
<Label row="1" class="itemCount" :text="
|
||||||
row="1"
|
|
||||||
class="itemCount"
|
|
||||||
:text="
|
|
||||||
`${recipe.combinations.length} ${
|
`${recipe.combinations.length} ${
|
||||||
recipe.combinations.length == 1
|
recipe.combinations.length == 1
|
||||||
? 'Combination'
|
? $options.filters.L('Combination')
|
||||||
: 'Combinations'
|
: $options.filters.L('Combinations')
|
||||||
}`
|
}`
|
||||||
"
|
" textWrap="true" />
|
||||||
textWrap="true"
|
|
||||||
/>
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<GridLayout
|
<GridLayout class="overviewItem" row="1" col="1" rows="auto, auto" columns="*">
|
||||||
class="overviewItem"
|
|
||||||
row="1"
|
|
||||||
col="1"
|
|
||||||
rows="auto, auto"
|
|
||||||
columns="*"
|
|
||||||
>
|
|
||||||
<MDRipple rowSpan="2" @tap="selectedTabIndex = 4" />
|
<MDRipple rowSpan="2" @tap="selectedTabIndex = 4" />
|
||||||
<Label row="0" class="bx" :text="icon.note" />
|
<Label row="0" class="bx" :text="icon.note" />
|
||||||
<Label
|
<Label row="1" class="itemCount" :text="
|
||||||
row="1"
|
|
||||||
class="itemCount"
|
|
||||||
:text="
|
|
||||||
`${recipe.notes.length} ${
|
`${recipe.notes.length} ${
|
||||||
recipe.notes.length == 1 ? 'Note' : 'Notes'
|
recipe.notes.length == 1
|
||||||
|
? $options.filters.L('Note')
|
||||||
|
: $options.filters.L('Notes')
|
||||||
}`
|
}`
|
||||||
"
|
" textWrap="true" />
|
||||||
textWrap="true"
|
|
||||||
/>
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
@ -220,166 +95,75 @@
|
||||||
</TabContentItem>
|
</TabContentItem>
|
||||||
<TabContentItem>
|
<TabContentItem>
|
||||||
<ScrollView @scroll="onScroll">
|
<ScrollView @scroll="onScroll">
|
||||||
<GridLayout
|
<GridLayout v-if="!recipe.ingredients.length" rows="*, auto, *, 88" columns="*" class="emptyStateContainer">
|
||||||
v-if="!recipe.ingredients.length"
|
|
||||||
rows="*, auto, *, 88"
|
|
||||||
columns="*"
|
|
||||||
class="emptyStateContainer"
|
|
||||||
>
|
|
||||||
<StackLayout col="0" row="1" class="emptyState">
|
<StackLayout col="0" row="1" class="emptyState">
|
||||||
<Label class="bx icon" :text="icon.item" textWrap="true" />
|
<Label class="bx icon" :text="icon.item" textWrap="true" />
|
||||||
<StackLayout orientation="horizontal" class="title orkm">
|
<Label class="subTitle orkm" :text="'Use the pencil button to add some ingredients' | L" textWrap="true" />
|
||||||
<Label text="Use the " />
|
|
||||||
<Label class="bx" :text="icon.edit" />
|
|
||||||
<Label text=" button" />
|
|
||||||
</StackLayout>
|
|
||||||
<Label text="to add some ingredients" textWrap="true" />
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<StackLayout v-else padding="24 16 72">
|
<StackLayout v-else padding="24 16 72">
|
||||||
<AbsoluteLayout class="inputField">
|
<AbsoluteLayout class="inputField">
|
||||||
<TextField
|
<TextField width="50%" v-model="yieldMultiplier" keyboardType="number" />
|
||||||
width="50%"
|
<Label top="0" class="fieldLabel" :text="`${$options.filters.L('Required')} ${$options.filters.L(recipe.yield.unit)}`" />
|
||||||
v-model="yieldMultiplier"
|
|
||||||
keyboardType="number"
|
|
||||||
/>
|
|
||||||
<Label
|
|
||||||
top="0"
|
|
||||||
class="fieldLabel"
|
|
||||||
:text="`Required ${recipe.yield.unit.toLowerCase()}`"
|
|
||||||
/>
|
|
||||||
</AbsoluteLayout>
|
</AbsoluteLayout>
|
||||||
<StackLayout margin="16 0">
|
<Label margin="16 0" class="subTitle orkm" :text="
|
||||||
<Label
|
`${$options.filters.L('Ingredients')} (${positiveYieldMultiplier} ${$options.filters.L(recipe.yield.unit)})`
|
||||||
class="title orkm"
|
" textWrap="true" />
|
||||||
:text="
|
<StackLayout v-for="(item, index) in recipe.ingredients" :key="index">
|
||||||
`Ingredients for ${positiveYieldMultiplier} ${recipe.yield.unit.toLowerCase()}`
|
<check-box class="ingredient" checkPadding="16" fillColor="#ff5200" :text="
|
||||||
"
|
|
||||||
textWrap="true"
|
|
||||||
/>
|
|
||||||
</StackLayout>
|
|
||||||
<StackLayout
|
|
||||||
v-for="(item, index) in recipe.ingredients"
|
|
||||||
:key="index"
|
|
||||||
>
|
|
||||||
<check-box
|
|
||||||
class="ingredient"
|
|
||||||
checkPadding="16"
|
|
||||||
fillColor="#ff5200"
|
|
||||||
:text="
|
|
||||||
`${
|
`${
|
||||||
roundedQuantity(item.quantity)
|
roundedQuantity(item.quantity)
|
||||||
? roundedQuantity(item.quantity) + ' '
|
? roundedQuantity(item.quantity) + ' '
|
||||||
: ''
|
: ''
|
||||||
}${roundedQuantity(item.quantity) ? item.unit + ' ' : ''}${
|
}${roundedQuantity(item.quantity) ? $options.filters.L(item.unit) + ' ' : ''}${
|
||||||
item.item
|
item.item
|
||||||
}`
|
}`
|
||||||
"
|
" />
|
||||||
/>
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</TabContentItem>
|
</TabContentItem>
|
||||||
<TabContentItem>
|
<TabContentItem>
|
||||||
<ScrollView @scroll="onScroll">
|
<ScrollView @scroll="onScroll">
|
||||||
<GridLayout
|
<GridLayout v-if="!recipe.instructions.length" rows="*, auto, *, 88" columns="*" class="emptyStateContainer">
|
||||||
v-if="!recipe.instructions.length"
|
|
||||||
rows="*, auto, *, 88"
|
|
||||||
columns="*"
|
|
||||||
class="emptyStateContainer"
|
|
||||||
>
|
|
||||||
<StackLayout col="0" row="1" class="emptyState">
|
<StackLayout col="0" row="1" class="emptyState">
|
||||||
<Label class="bx icon" :text="icon.step" textWrap="true" />
|
<Label class="bx icon" :text="icon.step" textWrap="true" />
|
||||||
<StackLayout orientation="horizontal" class="title orkm">
|
<Label class="subTitle orkm" :text="'Use the pencil button to add some instructions' | L" textWrap="true" />
|
||||||
<Label text="Use the " />
|
|
||||||
<Label class="bx" :text="icon.edit" />
|
|
||||||
<Label text=" button" />
|
|
||||||
</StackLayout>
|
|
||||||
<Label text="to add some instructions" textWrap="true" />
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<StackLayout v-else padding="28 16 62">
|
<StackLayout v-else padding="28 16 62">
|
||||||
<GridLayout
|
<GridLayout columns="auto ,*" v-for="(instruction, index) in recipe.instructions" :key="index">
|
||||||
columns="auto ,*"
|
<Label col="0" colSpan="2" class="instruction" :class="{
|
||||||
v-for="(instruction, index) in recipe.instructions"
|
|
||||||
:key="index"
|
|
||||||
>
|
|
||||||
<Label
|
|
||||||
col="0"
|
|
||||||
colSpan="2"
|
|
||||||
class="instruction"
|
|
||||||
:class="{
|
|
||||||
noBorder: index === recipe.instructions.length - 1,
|
noBorder: index === recipe.instructions.length - 1,
|
||||||
}"
|
}" :text="instruction" textWrap="true" />
|
||||||
:text="instruction"
|
<Label verticalAlignment="top" horizontalAlignment="center" class="count orkm" col="0" :text="index + 1" />
|
||||||
textWrap="true"
|
|
||||||
/>
|
|
||||||
<Label
|
|
||||||
verticalAlignment="top"
|
|
||||||
horizontalAlignment="center"
|
|
||||||
class="count orkm"
|
|
||||||
col="0"
|
|
||||||
:text="index + 1"
|
|
||||||
/>
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</TabContentItem>
|
</TabContentItem>
|
||||||
<TabContentItem>
|
<TabContentItem>
|
||||||
<ScrollView @scroll="onScroll">
|
<ScrollView @scroll="onScroll">
|
||||||
<GridLayout
|
<GridLayout v-if="!recipe.combinations.length" rows="*, auto, *, 88" columns="*" class="emptyStateContainer">
|
||||||
v-if="!recipe.combinations.length"
|
|
||||||
rows="*, auto, *, 88"
|
|
||||||
columns="*"
|
|
||||||
class="emptyStateContainer"
|
|
||||||
>
|
|
||||||
<StackLayout col="0" row="1" class="emptyState">
|
<StackLayout col="0" row="1" class="emptyState">
|
||||||
<Label class="bx icon" :text="icon.outline" textWrap="true" />
|
<Label class="bx icon" :text="icon.outline" textWrap="true" />
|
||||||
<StackLayout orientation="horizontal" class="title orkm">
|
<Label class="subTitle orkm" :text="'Use the pencil button to add some combinations' | L" textWrap="true" />
|
||||||
<Label text="Use the " />
|
|
||||||
<Label class="bx" :text="icon.edit" />
|
|
||||||
<Label text=" button" />
|
|
||||||
</StackLayout>
|
|
||||||
<Label text="to add some combinations" textWrap="true" />
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<StackLayout v-else padding="8 0 80">
|
<StackLayout v-else padding="8 0 80">
|
||||||
<GridLayout
|
<GridLayout columns="auto, *" v-for="(combination, index) in recipe.combinations" :key="index" androidElevation="1" class="urlCard">
|
||||||
columns="auto, *"
|
|
||||||
v-for="(combination, index) in recipe.combinations"
|
|
||||||
:key="index"
|
|
||||||
androidElevation="1"
|
|
||||||
class="urlCard"
|
|
||||||
>
|
|
||||||
<MDRipple colSpan="2" @tap="viewCombination(combination)" />
|
<MDRipple colSpan="2" @tap="viewCombination(combination)" />
|
||||||
<Label col="0" class="bx linkIcon" :text="icon.food" />
|
<Label col="0" class="bx linkIcon" :text="icon.food" />
|
||||||
<Label
|
<Label col="1" verticalAlignment="center" class="link" :text="getCombinationTitle(combination)" textWrap="true" />
|
||||||
col="1"
|
|
||||||
verticalAlignment="center"
|
|
||||||
class="link"
|
|
||||||
:text="getCombinationTitle(combination)"
|
|
||||||
textWrap="true"
|
|
||||||
/>
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</TabContentItem>
|
</TabContentItem>
|
||||||
<TabContentItem>
|
<TabContentItem>
|
||||||
<ScrollView @scroll="onScroll">
|
<ScrollView @scroll="onScroll">
|
||||||
<GridLayout
|
<GridLayout v-if="!recipe.notes.length" rows="*, auto, *, 88" columns="*" class="emptyStateContainer">
|
||||||
v-if="!recipe.notes.length"
|
|
||||||
rows="*, auto, *, 88"
|
|
||||||
columns="*"
|
|
||||||
class="emptyStateContainer"
|
|
||||||
>
|
|
||||||
<StackLayout col="0" row="1" class="emptyState">
|
<StackLayout col="0" row="1" class="emptyState">
|
||||||
<Label class="bx icon" :text="icon.note" textWrap="true" />
|
<Label class="bx icon" :text="icon.note" textWrap="true" />
|
||||||
<StackLayout orientation="horizontal" class="title orkm">
|
<Label class="subTitle orkm" :text="'Use the pencil button to add some notes' | L" textWrap="true" />
|
||||||
<Label text="Use the " />
|
|
||||||
<Label class="bx" :text="icon.edit" />
|
|
||||||
<Label text=" button" />
|
|
||||||
</StackLayout>
|
|
||||||
<Label text="to add some notes" textWrap="true" />
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<StackLayout v-else padding="8 0 80">
|
<StackLayout v-else padding="8 0 80">
|
||||||
|
@ -390,17 +174,11 @@
|
||||||
</Tabs>
|
</Tabs>
|
||||||
<GridLayout id="btnFabContainer" rows="*, auto" columns="*, auto">
|
<GridLayout id="btnFabContainer" rows="*, auto" columns="*, auto">
|
||||||
<transition name="dolly" appear>
|
<transition name="dolly" appear>
|
||||||
<MDFloatingActionButton
|
<MDFloatingActionButton row="1" col="1" src="res://share" @tap="shareHandler" v-if="showFab" />
|
||||||
row="1"
|
|
||||||
col="1"
|
|
||||||
src="res://share"
|
|
||||||
@tap="shareHandler"
|
|
||||||
v-if="showFab"
|
|
||||||
/>
|
|
||||||
</transition>
|
</transition>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</AbsoluteLayout>
|
</AbsoluteLayout>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -413,20 +191,32 @@ import {
|
||||||
Span,
|
Span,
|
||||||
FormattedString,
|
FormattedString,
|
||||||
Label,
|
Label,
|
||||||
} from "@nativescript/core"
|
Observable
|
||||||
import { Feedback, FeedbackType, FeedbackPosition } from "nativescript-feedback"
|
}
|
||||||
|
from "@nativescript/core"
|
||||||
|
import {
|
||||||
|
Feedback,
|
||||||
|
FeedbackType,
|
||||||
|
FeedbackPosition
|
||||||
|
}
|
||||||
|
from "nativescript-feedback"
|
||||||
import * as Toast from "nativescript-toast"
|
import * as Toast from "nativescript-toast"
|
||||||
import * as SocialShare from "@nativescript/social-share"
|
import * as SocialShare from "@nativescript/social-share"
|
||||||
import { mapActions, mapState } from "vuex"
|
import {
|
||||||
|
localize
|
||||||
|
}
|
||||||
|
from "@nativescript/localize"
|
||||||
|
import {
|
||||||
|
mapActions,
|
||||||
|
mapState
|
||||||
|
}
|
||||||
|
from "vuex"
|
||||||
import EditRecipe from "./EditRecipe.vue"
|
import EditRecipe from "./EditRecipe.vue"
|
||||||
import ViewRecipe from "./ViewRecipe.vue"
|
import ViewRecipe from "./ViewRecipe.vue"
|
||||||
import ShareChooser from "./modal/ShareChooser.vue"
|
import ShareChooser from "./modal/ShareChooser.vue"
|
||||||
|
|
||||||
let feedback = new Feedback()
|
let feedback = new Feedback()
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ["filterTrylater", "recipeID"],
|
props: [ "filterTrylater", "recipeID" ],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
busy: false,
|
busy: false,
|
||||||
|
@ -436,312 +226,269 @@ export default {
|
||||||
selectedTabIndex: 0,
|
selectedTabIndex: 0,
|
||||||
currentRecipeID: this.recipeID,
|
currentRecipeID: this.recipeID,
|
||||||
viewIsScrolled: false,
|
viewIsScrolled: false,
|
||||||
isScrolled: [false, false, false, false, false, false],
|
isScrolled: [ false, false, false, false, false, false ],
|
||||||
hideActionBar: false,
|
hideActionBar: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(["icon", "recipes"]),
|
...mapState( [ "icon", "recipes" ] ),
|
||||||
screenWidth() {
|
screenWidth() {
|
||||||
return Screen.mainScreen.widthDIPs
|
return Screen.mainScreen.widthDIPs
|
||||||
},
|
},
|
||||||
positiveYieldMultiplier() {
|
positiveYieldMultiplier() {
|
||||||
return Math.abs(this.yieldMultiplier) > 0
|
return Math.abs( this.yieldMultiplier ) > 0 ? Math.abs( parseFloat( this.yieldMultiplier ) ) : 1
|
||||||
? Math.abs(parseFloat(this.yieldMultiplier))
|
|
||||||
: 1
|
|
||||||
},
|
},
|
||||||
isLightMode() {
|
isLightMode() {
|
||||||
return Application.systemAppearance() === "light"
|
return Application.systemAppearance() === "light"
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions([
|
...mapActions( [ "toggleStateAction", "setCurrentComponentAction", "overwriteRecipeAction", "setRecipeAsTriedAction", ] ),
|
||||||
"toggleStateAction",
|
onPageLoad( args ) {
|
||||||
"setCurrentComponentAction",
|
const page = args.object;
|
||||||
"overwriteRecipeAction",
|
page.bindingContext = new Observable();
|
||||||
"setRecipeAsTriedAction",
|
|
||||||
]),
|
|
||||||
onPageLoad() {
|
|
||||||
this.busy = false
|
this.busy = false
|
||||||
setTimeout((e) => {
|
setTimeout( ( e ) => {
|
||||||
this.setCurrentComponentAction("ViewRecipe")
|
this.setCurrentComponentAction( "ViewRecipe" )
|
||||||
}, 500)
|
}, 500 )
|
||||||
this.showFab = true
|
this.showFab = true
|
||||||
this.yieldMultiplier = this.recipe.yield.quantity
|
this.yieldMultiplier = this.recipe.yield.quantity
|
||||||
this.keepScreenOn(true)
|
this.keepScreenOn( true )
|
||||||
this.syncCombinations()
|
this.syncCombinations()
|
||||||
},
|
},
|
||||||
onPageUnload() {
|
onPageUnload() {
|
||||||
feedback.hide()
|
feedback.hide()
|
||||||
this.keepScreenOn(false)
|
this.keepScreenOn( false )
|
||||||
},
|
},
|
||||||
|
|
||||||
// HELPERS
|
// HELPERS
|
||||||
niceDates(time) {
|
niceDates( time ) {
|
||||||
let lastTried = new Date(time).getTime()
|
let lastTried = new Date( time ).getTime()
|
||||||
let now = new Date().getTime()
|
let now = new Date().getTime()
|
||||||
let midnight = new Date().setHours(0, 0, 0, 0)
|
let midnight = new Date().setHours( 0, 0, 0, 0 )
|
||||||
let diff = (now - lastTried) / 1000
|
let diff = ( now - lastTried ) / 1000
|
||||||
let dayDiff = Math.ceil(diff / 86400)
|
let dayDiff = Math.ceil( diff / 86400 )
|
||||||
if (isNaN(dayDiff) || dayDiff < 0) return ""
|
if ( isNaN( dayDiff ) || dayDiff < 0 ) return ""
|
||||||
|
|
||||||
|
function duration( value ) {
|
||||||
|
return localize( value )
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
(diff < 86400 && lastTried > midnight && "today") ||
|
( diff < 86400 && lastTried > midnight && duration( "today" ) ) || ( dayDiff == 1 && "yesterday" ) || ( dayDiff < 7 && dayDiff + " " + duration( "days ago" ) ) || ( dayDiff < 31 && Math.round( dayDiff / 7 ) + " " + duration(
|
||||||
(dayDiff == 1 && "yesterday") ||
|
"weeks ago" ) ) || ( dayDiff <
|
||||||
(dayDiff < 7 && dayDiff + " days ago") ||
|
366 && Math.round(
|
||||||
(dayDiff < 31 && Math.round(dayDiff / 7) + " week(s) ago") ||
|
dayDiff /
|
||||||
(dayDiff < 366 && Math.round(dayDiff / 30) + " month(s) ago") ||
|
30 ) + " " + duration( "months ago" ) ) || ( dayDiff > 365 && duration( "long time ago" ) ) )
|
||||||
(dayDiff > 365 && "long time ago")
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
selectedIndexChange(args) {
|
selectedIndexChange( args ) {
|
||||||
this.selectedTabIndex = args.object.selectedIndex
|
this.selectedTabIndex = args.object.selectedIndex
|
||||||
this.viewIsScrolled = this.isScrolled[this.selectedTabIndex]
|
this.viewIsScrolled = this.isScrolled[ this.selectedTabIndex ]
|
||||||
},
|
},
|
||||||
showLastTried() {
|
showLastTried() {
|
||||||
feedback.show({
|
feedback.show( {
|
||||||
title: `You tried this recipe ${this.niceDates(
|
title: `${localize('You tried this recipe:')} ${this.niceDates(
|
||||||
this.recipe.lastTried
|
this.recipe.lastTried
|
||||||
)}!`,
|
)}`,
|
||||||
titleColor: new Color(`${this.isLightMode ? "#f1f3f5" : "#212529"}`),
|
titleColor: new Color( `${this.isLightMode ? "#f1f3f5" : "#212529"}` ),
|
||||||
backgroundColor: new Color("#ff5200"),
|
backgroundColor: new Color( "#ff5200" ),
|
||||||
})
|
} )
|
||||||
},
|
},
|
||||||
roundedQuantity(quantity) {
|
roundedQuantity( quantity ) {
|
||||||
return Math.abs(
|
return Math.abs( Math.round(
|
||||||
Math.round(
|
( quantity / this.recipe.yield.quantity ) * this.positiveYieldMultiplier * 100 ) / 100 )
|
||||||
(quantity / this.recipe.yield.quantity) *
|
|
||||||
this.positiveYieldMultiplier *
|
|
||||||
100
|
|
||||||
) / 100
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
keepScreenOn(boolean) {
|
keepScreenOn( boolean ) {
|
||||||
let activity =
|
let activity = Application.android.foregroundActivity || Application.android.startActivity
|
||||||
Application.android.foregroundActivity ||
|
|
||||||
Application.android.startActivity
|
|
||||||
let window = activity.getWindow()
|
let window = activity.getWindow()
|
||||||
if (boolean)
|
if ( boolean ) window.addFlags( android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON )
|
||||||
window.addFlags(
|
else window.clearFlags( android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON )
|
||||||
android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
|
|
||||||
)
|
|
||||||
else
|
|
||||||
window.clearFlags(
|
|
||||||
android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
formattedTime(time) {
|
formattedTime( time ) {
|
||||||
let t = time.split(":")
|
let t = time.split( ":" )
|
||||||
let h = parseInt(t[0])
|
let h = parseInt( t[ 0 ] )
|
||||||
let m = parseInt(t[1])
|
let m = parseInt( t[ 1 ] )
|
||||||
return h ? (m ? `${h} hr ${m} min` : `${h} hr`) : `${m} min`
|
let hr = localize( 'hr' )
|
||||||
|
let min = localize( 'min' )
|
||||||
|
return h ? ( m ? `${h} ${hr} ${m} ${min}` : `${h} ${hr}` ) : `${m} ${min}`
|
||||||
},
|
},
|
||||||
isValidURL(string) {
|
isValidURL( string ) {
|
||||||
let pattern = new RegExp("^https?|^www", "ig")
|
let pattern = new RegExp( "^https?|^www", "ig" )
|
||||||
return pattern.test(string)
|
return pattern.test( string )
|
||||||
},
|
},
|
||||||
getCombinationTitle(id) {
|
getCombinationTitle( id ) {
|
||||||
return this.recipes.filter((e) => e.id === id)[0].title
|
return this.recipes.filter( ( e ) => e.id === id )[ 0 ].title
|
||||||
},
|
},
|
||||||
syncCombinations() {
|
syncCombinations() {
|
||||||
let combinationForOtherRecipes = this.recipes
|
let combinationForOtherRecipes = this.recipes.filter(
|
||||||
.filter(
|
( e ) => e.combinations.indexOf( this.currentRecipeID ) >= 0 || this.recipe.combinations.includes( e.id ) ).map( ( e ) => e.id )
|
||||||
(e) =>
|
|
||||||
e.combinations.indexOf(this.currentRecipeID) >= 0 ||
|
|
||||||
this.recipe.combinations.includes(e.id)
|
|
||||||
)
|
|
||||||
.map((e) => e.id)
|
|
||||||
this.recipe.combinations = combinationForOtherRecipes
|
this.recipe.combinations = combinationForOtherRecipes
|
||||||
this.overwriteRecipeAction({
|
this.overwriteRecipeAction( {
|
||||||
id: this.currentRecipeID,
|
id: this.currentRecipeID,
|
||||||
recipe: this.recipe,
|
recipe: this.recipe,
|
||||||
})
|
} )
|
||||||
},
|
},
|
||||||
|
|
||||||
// NAVIGATION HANDLERS
|
// NAVIGATION HANDLERS
|
||||||
onScroll(args) {
|
onScroll( args ) {
|
||||||
this.viewIsScrolled = this.isScrolled[this.selectedTabIndex] =
|
this.viewIsScrolled = this.isScrolled[ this.selectedTabIndex ] = args.scrollY > 8 ? true : false
|
||||||
args.scrollY > 8 ? true : false
|
|
||||||
},
|
},
|
||||||
editRecipe() {
|
editRecipe() {
|
||||||
this.showFab = false
|
this.showFab = false
|
||||||
this.busy = true
|
this.busy = true
|
||||||
this.$navigateTo(EditRecipe, {
|
this.$navigateTo( EditRecipe, {
|
||||||
props: {
|
props: {
|
||||||
navigationFromView: true,
|
navigationFromView: true,
|
||||||
filterTrylater: this.filterTrylater,
|
filterTrylater: this.filterTrylater,
|
||||||
recipeID: this.currentRecipeID,
|
recipeID: this.currentRecipeID,
|
||||||
},
|
},
|
||||||
backstackVisible: false,
|
backstackVisible: false,
|
||||||
})
|
} )
|
||||||
},
|
},
|
||||||
viewCombination(combination) {
|
viewCombination( combination ) {
|
||||||
this.recipe = this.recipes.filter((e) => e.id === combination)[0]
|
this.recipe = this.recipes.filter( ( e ) => e.id === combination )[ 0 ]
|
||||||
this.currentRecipeID = combination
|
this.currentRecipeID = combination
|
||||||
this.syncCombinations()
|
this.syncCombinations()
|
||||||
this.selectedTabIndex = 0
|
this.selectedTabIndex = 0
|
||||||
setTimeout(
|
setTimeout(
|
||||||
(e) =>
|
( e ) => this.recipe.tried && this.recipe.lastTried && this.showLastTried(), 500 )
|
||||||
this.recipe.tried && this.recipe.lastTried && this.showLastTried(),
|
|
||||||
500
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// SHARE ACTION
|
// SHARE ACTION
|
||||||
shareHandler() {
|
shareHandler() {
|
||||||
if (this.recipe.imageSrc) {
|
if ( this.recipe.imageSrc ) {
|
||||||
this.$showModal(ShareChooser, {
|
this.$showModal( ShareChooser, {
|
||||||
props: {
|
props: {
|
||||||
title: "Share",
|
title: "Share",
|
||||||
},
|
},
|
||||||
}).then((result) => {
|
} ).then( ( result ) => {
|
||||||
switch (result) {
|
switch ( result ) {
|
||||||
case "photo":
|
case "photo":
|
||||||
ImageSource.fromFile(this.recipe.imageSrc).then((res) => {
|
ImageSource.fromFile( this.recipe.imageSrc ).then( ( res ) => {
|
||||||
SocialShare.shareImage(res, "Share recipe photo using")
|
SocialShare.shareImage( res, "Share recipe photo using" )
|
||||||
})
|
} )
|
||||||
break
|
break
|
||||||
case "recipe":
|
case "recipe":
|
||||||
this.shareRecipe()
|
this.shareRecipe()
|
||||||
break
|
break
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
})
|
} )
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
this.shareRecipe()
|
this.shareRecipe()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
shareRecipe() {
|
shareRecipe() {
|
||||||
let overview = `${
|
let overview = `${
|
||||||
this.recipe.title
|
this.recipe.title
|
||||||
}\n\nPreparation time: ${this.formattedTime(
|
}\n\n${localize("Preparation time")}: ${this.formattedTime(
|
||||||
this.recipe.prepTime
|
this.recipe.prepTime
|
||||||
)}\nCooking time: ${this.formattedTime(this.recipe.cookTime)}\n`
|
)}\n${localize( "Cooking time" )}: ${this.formattedTime(this.recipe.cookTime)}\n`
|
||||||
let shareContent = overview
|
let shareContent = overview
|
||||||
if (this.recipe.ingredients.length) {
|
if ( this.recipe.ingredients.length ) {
|
||||||
let ingredients = `\n\nIngredients for ${
|
let ingredients = `\n\n${localize( "Ingredients" )} (${
|
||||||
this.yieldMultiplier
|
this.yieldMultiplier
|
||||||
} ${this.recipe.yield.unit.toLowerCase()}\n\n`
|
} ${localize( this.recipe.yield.unit )})\n\n`
|
||||||
this.recipe.ingredients.forEach((e) => {
|
this.recipe.ingredients.forEach( ( e ) => {
|
||||||
ingredients += `- ${
|
ingredients += `- ${
|
||||||
e.quantity
|
e.quantity
|
||||||
? this.roundedQuantity(e.quantity) + " " + e.unit + " "
|
? this.roundedQuantity(e.quantity) + " " + e.unit + " "
|
||||||
: ""
|
: ""
|
||||||
}${e.item}\n`
|
}${e.item}\n`
|
||||||
})
|
} )
|
||||||
shareContent += ingredients
|
shareContent += ingredients
|
||||||
}
|
}
|
||||||
if (this.recipe.instructions.length) {
|
if ( this.recipe.instructions.length ) {
|
||||||
let instructions = `\n\nInstructions:\n\n`
|
let instructions = `\n\n${localize( "Instructions" )}:\n\n`
|
||||||
this.recipe.instructions.forEach((e, i) => {
|
this.recipe.instructions.forEach( ( e, i ) => {
|
||||||
instructions += `Step ${i + 1}: ${e}\n\n`
|
instructions += `${i + 1}. ${e}\n\n`
|
||||||
})
|
} )
|
||||||
shareContent += instructions
|
shareContent += instructions
|
||||||
}
|
}
|
||||||
if (this.recipe.combinations.length) {
|
if ( this.recipe.combinations.length ) {
|
||||||
let combinations = `\nCombinations:\n\n`
|
let combinations = `\n${localize( "Combinations" )}:\n\n`
|
||||||
this.recipe.combinations.forEach((e, i) => {
|
this.recipe.combinations.forEach( ( e, i ) => {
|
||||||
combinations += `${i + 1}. ${this.getCombinationTitle(e)}\n\n`
|
combinations += `${i + 1}. ${this.getCombinationTitle(e)}\n\n`
|
||||||
})
|
} )
|
||||||
shareContent += combinations
|
shareContent += combinations
|
||||||
}
|
}
|
||||||
if (this.recipe.notes.length) {
|
if ( this.recipe.notes.length ) {
|
||||||
let notes = `\nNotes:\n\n`
|
let notes = `\n${localize( "Notes" )}:\n\n`
|
||||||
this.recipe.notes.forEach((e, i) => {
|
this.recipe.notes.forEach( ( e, i ) => {
|
||||||
notes += `${i + 1}. ${e}\n\n`
|
notes += `${i + 1}. ${e}\n\n`
|
||||||
})
|
} )
|
||||||
shareContent += notes
|
shareContent += notes
|
||||||
}
|
}
|
||||||
let sharenote =
|
let sharenote = '\n' + localize( "Shared via EnRecipes. Get it on Play Store or F-Droid." )
|
||||||
"\nCreated and shared via EnRecipes. Get it on Play Store or F-Droid."
|
|
||||||
|
|
||||||
shareContent += sharenote
|
shareContent += sharenote
|
||||||
|
SocialShare.shareText( shareContent, "Share recipe using" )
|
||||||
SocialShare.shareText(shareContent, "Share recipe using")
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// DATA HANDLERS
|
// DATA HANDLERS
|
||||||
toggle(key, setDate) {
|
toggle( key, setDate ) {
|
||||||
this.toggleStateAction({
|
this.toggleStateAction( {
|
||||||
id: this.currentRecipeID,
|
id: this.currentRecipeID,
|
||||||
recipe: this.recipe,
|
recipe: this.recipe,
|
||||||
key,
|
key,
|
||||||
setDate,
|
setDate,
|
||||||
})
|
} )
|
||||||
},
|
},
|
||||||
toggleFavorite() {
|
toggleFavourite() {
|
||||||
this.recipe.isFavorite
|
this.recipe.isFavorite ? Toast.makeText( localize( "Removed from Favourites" ) ).show() : Toast.makeText( localize( "Added to Favourites" ) ).show()
|
||||||
? Toast.makeText("Removed from Favorites").show()
|
this.toggle( "isFavorite" )
|
||||||
: Toast.makeText("Added to Favorites").show()
|
|
||||||
this.toggle("isFavorite")
|
|
||||||
},
|
},
|
||||||
toggleTrylater() {
|
toggleTrylater() {
|
||||||
this.recipe.tried
|
this.recipe.tried ? Toast.makeText( localize( "Added to Try Later" ) ).show() : Toast.makeText(
|
||||||
? this.filterTrylater
|
localize( "Removed from Try Later" ) ).show()
|
||||||
? Toast.makeText("Added back to Try Later").show()
|
this.toggle( "tried" )
|
||||||
: Toast.makeText("Added to Try Later").show()
|
|
||||||
: this.filterTrylater
|
|
||||||
? Toast.makeText("You tried this recipe").show()
|
|
||||||
: Toast.makeText("Removed from Try Later").show()
|
|
||||||
this.toggle("tried")
|
|
||||||
},
|
},
|
||||||
recipeTried() {
|
recipeTried() {
|
||||||
this.setRecipeAsTriedAction({
|
this.setRecipeAsTriedAction( {
|
||||||
id: this.currentRecipeID,
|
id: this.currentRecipeID,
|
||||||
recipe: this.recipe,
|
recipe: this.recipe,
|
||||||
})
|
} )
|
||||||
this.$navigateBack()
|
this.$navigateBack()
|
||||||
},
|
},
|
||||||
|
|
||||||
// NOTES
|
// NOTES
|
||||||
createNote(note) {
|
createNote( note ) {
|
||||||
const vm = this
|
const vm = this
|
||||||
let regex = /(https?:\/\/[^\s]+)/g
|
let regex = /(https?:\/\/[^\s]+)/g
|
||||||
let label = new Label()
|
let label = new Label()
|
||||||
label.class = "textCard"
|
label.class = "textCard"
|
||||||
label.textWrap = true
|
label.textWrap = true
|
||||||
let formattedString = new FormattedString()
|
let formattedString = new FormattedString()
|
||||||
let textArray = note.split(regex)
|
let textArray = note.split( regex )
|
||||||
|
|
||||||
function createSpan(text, isUrl) {
|
function createSpan( text, isUrl ) {
|
||||||
let span = new Span()
|
let span = new Span()
|
||||||
span.text = text
|
span.text = text
|
||||||
span.fontSize = 16
|
span.fontSize = 16
|
||||||
if (isUrl) {
|
if ( isUrl ) {
|
||||||
span.textDecoration = "underline"
|
span.textDecoration = "underline"
|
||||||
span.color = "#ff5200"
|
span.color = "#ff5200"
|
||||||
span.on("linkTap", () => Utils.openUrl(text))
|
span.on( "linkTap", () => Utils.openUrl( text ) )
|
||||||
}
|
}
|
||||||
formattedString.spans.push(span)
|
formattedString.spans.push( span )
|
||||||
}
|
}
|
||||||
|
textArray.forEach( ( text ) => {
|
||||||
textArray.forEach((text) => {
|
createSpan( text, regex.test( text ) )
|
||||||
createSpan(text, regex.test(text))
|
} )
|
||||||
})
|
|
||||||
|
|
||||||
label.formattedText = formattedString
|
label.formattedText = formattedString
|
||||||
|
|
||||||
return label
|
return label
|
||||||
},
|
},
|
||||||
createNotes(args) {
|
createNotes( args ) {
|
||||||
const stack = args.object
|
const stack = args.object
|
||||||
if (!stack.getChildrenCount()) {
|
if ( !stack.getChildrenCount() ) {
|
||||||
this.recipe.notes.forEach((note) => {
|
this.recipe.notes.forEach( ( note ) => {
|
||||||
stack.addChild(this.createNote(note))
|
stack.addChild( this.createNote( note ) )
|
||||||
})
|
} )
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.recipe = this.recipes.filter((e) => e.id === this.currentRecipeID)[0]
|
this.recipe = this.recipes.filter( ( e ) => e.id === this.currentRecipeID )[ 0 ]
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.showFab = true
|
this.showFab = true
|
||||||
setTimeout(
|
setTimeout(
|
||||||
(e) => this.recipe.tried && this.recipe.lastTried && this.showLastTried(),
|
( e ) => this.recipe.tried && this.recipe.lastTried && this.showLastTried(), 500 )
|
||||||
500
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,67 +1,44 @@
|
||||||
<template>
|
<template>
|
||||||
<Page>
|
<Page>
|
||||||
<StackLayout class="dialogContainer" :class="appTheme">
|
<StackLayout class="dialogContainer" :class="appTheme">
|
||||||
<Label class="dialogTitle orkm" :text="title" />
|
<Label class="dialogTitle orkm" :text="`${title}` | L" />
|
||||||
<ScrollView width="100%" :height="height ? height : screenHeight - 256">
|
<ScrollView width="100%" :height="height ? height : screenHeight - 256">
|
||||||
<StackLayout>
|
<StackLayout>
|
||||||
<MDButton
|
<MDButton v-for="(item, index) in list" :key="index" class="actionItem" variant="text" :rippleColor="rippleColor" :text="`${item}` | L" @loaded="onLabelLoaded" @tap="tapAction(item)" />
|
||||||
v-for="(item, index) in list"
|
|
||||||
:key="index"
|
|
||||||
class="actionItem"
|
|
||||||
variant="text"
|
|
||||||
:rippleColor="rippleColor"
|
|
||||||
:text="item"
|
|
||||||
@loaded="onLabelLoaded"
|
|
||||||
@tap="tapAction(item)"
|
|
||||||
/>
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
<GridLayout rows="auto" columns="auto, *, auto" class="actionsContainer">
|
<GridLayout rows="auto" columns="auto, *, auto" class="actionsContainer">
|
||||||
<MDButton
|
<MDButton :rippleColor="rippleColor" variant="text" v-if="action" col="0" class="action orkm pull-left" :text="`${action}` | L" @tap="$modal.close(action)" />
|
||||||
:rippleColor="rippleColor"
|
<MDButton :rippleColor="rippleColor" variant="text" col="2" class="action orkm pull-right" :text="'CANCEL' | L" @tap="$modal.close(false)" />
|
||||||
variant="text"
|
|
||||||
v-if="action"
|
|
||||||
col="0"
|
|
||||||
class="action orkm pull-left"
|
|
||||||
:text="action"
|
|
||||||
@tap="$modal.close(action)"
|
|
||||||
/>
|
|
||||||
<MDButton
|
|
||||||
:rippleColor="rippleColor"
|
|
||||||
variant="text"
|
|
||||||
col="2"
|
|
||||||
class="action orkm pull-right"
|
|
||||||
text="CANCEL"
|
|
||||||
@tap="$modal.close(false)"
|
|
||||||
/>
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { Application, Screen } from "@nativescript/core"
|
import {
|
||||||
|
Application,
|
||||||
|
Screen
|
||||||
|
} from "@nativescript/core"
|
||||||
export default {
|
export default {
|
||||||
props: ["title", "list", "height", "action"],
|
props: [ "title", "list", "height", "action" ],
|
||||||
computed: {
|
computed: {
|
||||||
appTheme() {
|
appTheme() {
|
||||||
return Application.systemAppearance()
|
return Application.systemAppearance()
|
||||||
},
|
},
|
||||||
rippleColor() {
|
rippleColor() {
|
||||||
return this.appTheme == "light"
|
return this.appTheme == "light" ? "rgba(134,142,150,0.2)" : "rgba(206,212,218,0.1)"
|
||||||
? "rgba(134,142,150,0.2)"
|
|
||||||
: "rgba(206,212,218,0.1)"
|
|
||||||
},
|
},
|
||||||
screenHeight() {
|
screenHeight() {
|
||||||
return Math.round(Screen.mainScreen.heightDIPs)
|
return Math.round( Screen.mainScreen.heightDIPs )
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
tapAction(item) {
|
tapAction( item ) {
|
||||||
this.$modal.close(item)
|
this.$modal.close( item )
|
||||||
},
|
},
|
||||||
onLabelLoaded(args) {
|
onLabelLoaded( args ) {
|
||||||
args.object.android.setGravity(16)
|
args.object.android.setGravity( 16 )
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,62 +1,32 @@
|
||||||
<template>
|
<template>
|
||||||
<Page>
|
<Page>
|
||||||
<StackLayout class="dialogContainer" :class="appTheme">
|
<StackLayout class="dialogContainer" :class="appTheme">
|
||||||
<Label class="dialogTitle orkm" :text="title" />
|
<Label class="dialogTitle orkm" :text="`${title}` | L" textWrap='true' />
|
||||||
<StackLayout
|
<StackLayout v-if="filteredRecipes.length || searchTerm" padding="0 24 24">
|
||||||
v-if="filteredRecipes.length || searchTerm"
|
<TextField :hint="'Search' | L" v-model="searchTerm" />
|
||||||
padding="0 24 24"
|
|
||||||
>
|
|
||||||
<TextField hint="Search" v-model="searchTerm" />
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<ScrollView width="100%" :height="height ? height : screenHeight - 320">
|
<ScrollView width="100%" :height="height ? height : screenHeight - 320">
|
||||||
<StackLayout>
|
<StackLayout>
|
||||||
<MDButton
|
<MDButton v-for="(recipe, index) in filteredRecipes" :key="index" class="actionItem" variant="text" :rippleColor="rippleColor" :text="recipe.title" @loaded="onLabelLoaded" @tap="tapAction(recipe)" />
|
||||||
v-for="(recipe, index) in filteredRecipes"
|
<Label padding="24" lineHeight="6" v-if="!filteredRecipes.length" :text="'Nothing here! Add some recipes and try again.' | L" textAlignment="center" textWrap="true" />
|
||||||
:key="index"
|
|
||||||
class="actionItem"
|
|
||||||
variant="text"
|
|
||||||
:rippleColor="rippleColor"
|
|
||||||
:text="recipe.title"
|
|
||||||
@loaded="onLabelLoaded"
|
|
||||||
@tap="tapAction(recipe)"
|
|
||||||
/>
|
|
||||||
<Label
|
|
||||||
padding="24"
|
|
||||||
lineHeight="6"
|
|
||||||
v-if="!filteredRecipes.length"
|
|
||||||
text="Nothing here! Add some recipes and try again."
|
|
||||||
textAlignment="center"
|
|
||||||
textWrap="true"
|
|
||||||
/>
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
<GridLayout rows="auto" columns="auto, *, auto" class="actionsContainer">
|
<GridLayout rows="auto" columns="auto, *, auto" class="actionsContainer">
|
||||||
<MDButton
|
<MDButton :rippleColor="rippleColor" variant="text" v-if="action" col="0" class="action orkm pull-left" :text="`${action}` | L" @tap="$modal.close(action)" />
|
||||||
:rippleColor="rippleColor"
|
<MDButton :rippleColor="rippleColor" variant="text" col="2" class="action orkm pull-right" :text="'CANCEL' | L" @tap="$modal.close(false)" />
|
||||||
variant="text"
|
|
||||||
v-if="action"
|
|
||||||
col="0"
|
|
||||||
class="action orkm pull-left"
|
|
||||||
:text="action"
|
|
||||||
@tap="$modal.close(action)"
|
|
||||||
/>
|
|
||||||
<MDButton
|
|
||||||
:rippleColor="rippleColor"
|
|
||||||
variant="text"
|
|
||||||
col="2"
|
|
||||||
class="action orkm pull-right"
|
|
||||||
text="CANCEL"
|
|
||||||
@tap="$modal.close(false)"
|
|
||||||
/>
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { Application, Screen } from "@nativescript/core"
|
import {
|
||||||
|
Application,
|
||||||
|
Screen
|
||||||
|
}
|
||||||
|
from "@nativescript/core"
|
||||||
export default {
|
export default {
|
||||||
props: ["title", "recipes", "height", "action"],
|
props: [ "title", "recipes", "height", "action" ],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
searchTerm: "",
|
searchTerm: "",
|
||||||
|
@ -67,30 +37,26 @@ export default {
|
||||||
return Application.systemAppearance()
|
return Application.systemAppearance()
|
||||||
},
|
},
|
||||||
rippleColor() {
|
rippleColor() {
|
||||||
return this.appTheme == "light"
|
return this.appTheme == "light" ? "rgba(134,142,150,0.2)" : "rgba(206,212,218,0.1)"
|
||||||
? "rgba(134,142,150,0.2)"
|
|
||||||
: "rgba(206,212,218,0.1)"
|
|
||||||
},
|
},
|
||||||
screenHeight() {
|
screenHeight() {
|
||||||
return Math.round(Screen.mainScreen.heightDIPs)
|
return Math.round( Screen.mainScreen.heightDIPs )
|
||||||
},
|
},
|
||||||
filteredRecipes() {
|
filteredRecipes() {
|
||||||
return this.recipes
|
return this.recipes.map( ( e, i ) => {
|
||||||
.map((e, i) => {
|
|
||||||
return {
|
return {
|
||||||
id: e.id,
|
id: e.id,
|
||||||
title: e.title,
|
title: e.title,
|
||||||
}
|
}
|
||||||
})
|
} ).filter( ( e ) => e.title.includes( this.searchTerm ) )
|
||||||
.filter((e) => e.title.includes(this.searchTerm))
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
tapAction(recipe) {
|
tapAction( recipe ) {
|
||||||
this.$modal.close(recipe.id)
|
this.$modal.close( recipe.id )
|
||||||
},
|
},
|
||||||
onLabelLoaded(args) {
|
onLabelLoaded( args ) {
|
||||||
args.object.android.setGravity(16)
|
args.object.android.setGravity( 16 )
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,47 +1,31 @@
|
||||||
<template>
|
<template>
|
||||||
<Page>
|
<Page>
|
||||||
<StackLayout class="dialogContainer" :class="appTheme">
|
<StackLayout class="dialogContainer" :class="appTheme">
|
||||||
<Label class="dialogTitle orkm" :text="title" textWrap="true"/>
|
<Label class="dialogTitle orkm" :text="`${title}` | L" textWrap="true" />
|
||||||
<Label
|
<Label v-if="description" class="dialogDescription" :text="description" textWrap="true" />
|
||||||
v-if="description"
|
|
||||||
class="dialogDescription"
|
|
||||||
:text="description"
|
|
||||||
textWrap="true"
|
|
||||||
/>
|
|
||||||
<GridLayout rows="auto" columns="*, auto, auto" class="actionsContainer">
|
<GridLayout rows="auto" columns="*, auto, auto" class="actionsContainer">
|
||||||
<MDButton
|
<MDButton :rippleColor="rippleColor" variant="text" col="1" class="action orkm" :text="`${cancelButtonText}` | L" @tap="$modal.close(false)" />
|
||||||
:rippleColor="rippleColor"
|
<MDButton :rippleColor="rippleColor" variant="text" col="2" class="action orkm" :text="`${okButtonText}` | L" @tap="$modal.close(true)" />
|
||||||
variant="text"
|
|
||||||
col="1"
|
|
||||||
class="action orkm"
|
|
||||||
:text="cancelButtonText"
|
|
||||||
@tap="$modal.close(false)"
|
|
||||||
/>
|
|
||||||
<MDButton
|
|
||||||
:rippleColor="rippleColor"
|
|
||||||
variant="text"
|
|
||||||
col="2"
|
|
||||||
class="action orkm"
|
|
||||||
:text="okButtonText"
|
|
||||||
@tap="$modal.close(true)"
|
|
||||||
/>
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { Application } from "@nativescript/core"
|
import {
|
||||||
|
Application
|
||||||
|
}
|
||||||
|
from "@nativescript/core"
|
||||||
export default {
|
export default {
|
||||||
props: ["title", "description", "cancelButtonText", "okButtonText"],
|
props: [ "title", "description", "cancelButtonText", "okButtonText" ],
|
||||||
computed: {
|
computed: {
|
||||||
appTheme() {
|
appTheme() {
|
||||||
return Application.systemAppearance()
|
return Application.systemAppearance()
|
||||||
},
|
},
|
||||||
rippleColor() {
|
rippleColor() {
|
||||||
return this.appTheme == "light"
|
return this.appTheme == "light" ?
|
||||||
? "rgba(134,142,150,0.2)"
|
"rgba(134,142,150,0.2)" :
|
||||||
: "rgba(206,212,218,0.1)"
|
"rgba(206,212,218,0.1)"
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,138 +1,73 @@
|
||||||
<template>
|
<template>
|
||||||
<Page>
|
<Page>
|
||||||
<StackLayout class="dialogContainer" :class="appTheme">
|
<StackLayout class="dialogContainer" :class="appTheme">
|
||||||
<Label class="dialogTitle orkm" :text="title" />
|
<Label class="dialogTitle orkm" :text="`${title}` | L" />
|
||||||
<StackLayout
|
<StackLayout class="dialogListPicker" orientation="horizontal" horizontalAlignment="center">
|
||||||
class="dialogListPicker"
|
<ListPicker ref="hrPicker" :items="hrsList" :selectedIndex="hrIndex" @selectedIndexChange="setHrs"></ListPicker>
|
||||||
orientation="horizontal"
|
<ListPicker ref="minPicker" :items="minsList" :selectedIndex="minIndex" @selectedIndexChange="setMins"></ListPicker>
|
||||||
horizontalAlignment="center"
|
|
||||||
>
|
|
||||||
<ListPicker
|
|
||||||
ref="hrPicker"
|
|
||||||
:items="hrs"
|
|
||||||
:selectedIndex="hrIndex"
|
|
||||||
@selectedIndexChange="setHrs"
|
|
||||||
></ListPicker>
|
|
||||||
<ListPicker
|
|
||||||
ref="minPicker"
|
|
||||||
:items="mins"
|
|
||||||
:selectedIndex="minIndex"
|
|
||||||
@selectedIndexChange="setMins"
|
|
||||||
></ListPicker>
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<GridLayout rows="auto" columns="*, auto, auto" class="actionsContainer">
|
<GridLayout rows="auto" columns="*, auto, auto" class="actionsContainer">
|
||||||
<MDButton
|
<MDButton :rippleColor="rippleColor" variant="text" col="1" class="action orkm" :text="'CANCEL' | L" @tap="$modal.close(false)" />
|
||||||
:rippleColor="rippleColor"
|
<MDButton :rippleColor="rippleColor" variant="text" col="2" class="action orkm" :text="`${action}` | L" @tap="$modal.close(selectedTime)" />
|
||||||
variant="text"
|
|
||||||
col="1"
|
|
||||||
class="action orkm"
|
|
||||||
text="CANCEL"
|
|
||||||
@tap="$modal.close(false)"
|
|
||||||
/>
|
|
||||||
<MDButton
|
|
||||||
:rippleColor="rippleColor"
|
|
||||||
variant="text"
|
|
||||||
col="2"
|
|
||||||
class="action orkm"
|
|
||||||
:text="action"
|
|
||||||
@tap="$modal.close(selectedTime)"
|
|
||||||
/>
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { Application } from "@nativescript/core"
|
import {
|
||||||
|
Application
|
||||||
|
}
|
||||||
|
from "@nativescript/core"
|
||||||
|
import {
|
||||||
|
localize
|
||||||
|
}
|
||||||
|
from "@nativescript/localize"
|
||||||
export default {
|
export default {
|
||||||
props: ["title", "selectedHr", "selectedMin", "action"],
|
props: [ "title", "selectedHr", "selectedMin", "action" ],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
hrs: [
|
hrs: [],
|
||||||
"0 hr",
|
mins: [],
|
||||||
"1 hr",
|
|
||||||
"2 hr",
|
|
||||||
"3 hr",
|
|
||||||
"4 hr",
|
|
||||||
"5 hr",
|
|
||||||
"6 hr",
|
|
||||||
"7 hr",
|
|
||||||
"8 hr",
|
|
||||||
"9 hr",
|
|
||||||
"10 hr",
|
|
||||||
"11 hr",
|
|
||||||
"12 hr",
|
|
||||||
"13 hr",
|
|
||||||
"14 hr",
|
|
||||||
"15 hr",
|
|
||||||
"16 hr",
|
|
||||||
"17 hr",
|
|
||||||
"18 hr",
|
|
||||||
"19 hr",
|
|
||||||
"20 hr",
|
|
||||||
"21 hr",
|
|
||||||
"22 hr",
|
|
||||||
"23 hr",
|
|
||||||
],
|
|
||||||
mins: [
|
|
||||||
"0 min",
|
|
||||||
"1 min",
|
|
||||||
"2 min",
|
|
||||||
"3 min",
|
|
||||||
"4 min",
|
|
||||||
"5 min",
|
|
||||||
"6 min",
|
|
||||||
"7 min",
|
|
||||||
"8 min",
|
|
||||||
"9 min",
|
|
||||||
"10 min",
|
|
||||||
"15 min",
|
|
||||||
"20 min",
|
|
||||||
"25 min",
|
|
||||||
"30 min",
|
|
||||||
"35 min",
|
|
||||||
"40 min",
|
|
||||||
"45 min",
|
|
||||||
"50 min",
|
|
||||||
"55 min",
|
|
||||||
],
|
|
||||||
selectedHrs: "00",
|
selectedHrs: "00",
|
||||||
selectedMins: "00",
|
selectedMins: "00",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
hrsList() {
|
||||||
|
let h = [ ...Array( 24 ).keys() ]
|
||||||
|
this.hrs = h
|
||||||
|
return h.map( e => `${e} ${localize( 'hr' )}` )
|
||||||
|
},
|
||||||
|
minsList() {
|
||||||
|
let m = [ ...new Set( [ ...Array( 11 ).keys(), ...Array.from( Array( 12 ), ( _, x ) => x * 5 ) ] ) ]
|
||||||
|
this.mins = m
|
||||||
|
return m.map( e => `${e} ${localize( 'min' )}` )
|
||||||
|
},
|
||||||
hrIndex() {
|
hrIndex() {
|
||||||
let hr = this.selectedHr
|
return this.hrs.indexOf( parseInt( this.selectedHr ) )
|
||||||
if (hr.charAt(0) == "0") hr = hr.slice(-1) + " hr"
|
|
||||||
else hr = hr + " hr"
|
|
||||||
return this.hrs.indexOf(hr)
|
|
||||||
},
|
},
|
||||||
minIndex() {
|
minIndex() {
|
||||||
let min = this.selectedMin
|
return this.mins.indexOf( parseInt( this.selectedMin ) )
|
||||||
if (min.charAt(0) == "0") min = min.slice(-1) + " min"
|
|
||||||
else min = min + " min"
|
|
||||||
return this.mins.indexOf(min)
|
|
||||||
},
|
},
|
||||||
appTheme() {
|
appTheme() {
|
||||||
return Application.systemAppearance()
|
return Application.systemAppearance()
|
||||||
},
|
},
|
||||||
rippleColor() {
|
rippleColor() {
|
||||||
return this.appTheme == "light"
|
return this.appTheme == "light" ? "rgba(134,142,150,0.2)" : "rgba(206,212,218,0.1)"
|
||||||
? "rgba(134,142,150,0.2)"
|
|
||||||
: "rgba(206,212,218,0.1)"
|
|
||||||
},
|
},
|
||||||
selectedTime() {
|
selectedTime() {
|
||||||
return this.selectedHrs + ":" + this.selectedMins
|
return this.selectedHrs + ":" + this.selectedMins
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setHrs(args) {
|
setHrs( args ) {
|
||||||
let hr = "0" + this.hrs[args.object.selectedIndex]
|
let hr = "0" + this.hrs[ args.object.selectedIndex ]
|
||||||
this.selectedHrs = hr.slice(-5).slice(0, -3)
|
this.selectedHrs = hr.slice( -2 )
|
||||||
},
|
},
|
||||||
setMins(args) {
|
setMins( args ) {
|
||||||
let min = "0" + this.mins[args.object.selectedIndex]
|
let min = "0" + this.mins[ args.object.selectedIndex ]
|
||||||
this.selectedMins = min.slice(-6).slice(0, -4)
|
this.selectedMins = min.slice( -2 )
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,41 +1,30 @@
|
||||||
<template>
|
<template>
|
||||||
<Page>
|
<Page>
|
||||||
<StackLayout class="dialogContainer" :class="appTheme">
|
<StackLayout class="dialogContainer" :class="appTheme">
|
||||||
<Label class="dialogTitle orkm" :text="title" />
|
<Label class="dialogTitle orkm" :text="`${title}` | L" textWrap='true' />
|
||||||
<StackLayout class="dialogInput">
|
<StackLayout class="dialogInput">
|
||||||
<TextField
|
<TextField @loaded="focusField" :hint="hint ? hint : ''" v-model="category" autocapitalizationType="words" />
|
||||||
@loaded="focusField"
|
|
||||||
:hint="hint ? hint : ''"
|
|
||||||
v-model="category"
|
|
||||||
autocapitalizationType="words"
|
|
||||||
/>
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<GridLayout rows="auto" columns="*, auto, auto" class="actionsContainer">
|
<GridLayout rows="auto" columns="*, auto, auto" class="actionsContainer">
|
||||||
<MDButton
|
<MDButton :rippleColor="rippleColor" variant="text" col="1" class="action orkm" :text="'CANCEL' | L" @tap="$modal.close(false)" />
|
||||||
:rippleColor="rippleColor"
|
<MDButton :rippleColor="rippleColor" variant="text" col="2" class="action orkm" :text="`${action}` | L" @tap="$modal.close(category)" />
|
||||||
variant="text"
|
|
||||||
col="1"
|
|
||||||
class="action orkm"
|
|
||||||
text="CANCEL"
|
|
||||||
@tap="$modal.close(false)"
|
|
||||||
/>
|
|
||||||
<MDButton
|
|
||||||
:rippleColor="rippleColor"
|
|
||||||
variant="text"
|
|
||||||
col="2"
|
|
||||||
class="action orkm"
|
|
||||||
:text="action"
|
|
||||||
@tap="$modal.close(category)"
|
|
||||||
/>
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { Application, Utils } from "@nativescript/core"
|
import {
|
||||||
|
Application,
|
||||||
|
Utils
|
||||||
|
}
|
||||||
|
from "@nativescript/core"
|
||||||
|
import {
|
||||||
|
localize
|
||||||
|
}
|
||||||
|
from '@nativescript/localize'
|
||||||
export default {
|
export default {
|
||||||
props: ["title", "hint", "text", "action"],
|
props: [ "title", "hint", "text", "action" ],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
category: null,
|
category: null,
|
||||||
|
@ -46,20 +35,18 @@ export default {
|
||||||
return Application.systemAppearance()
|
return Application.systemAppearance()
|
||||||
},
|
},
|
||||||
rippleColor() {
|
rippleColor() {
|
||||||
return this.appTheme == "light"
|
return this.appTheme == "light" ? "rgba(134,142,150,0.2)" : "rgba(206,212,218,0.1)"
|
||||||
? "rgba(134,142,150,0.2)"
|
|
||||||
: "rgba(206,212,218,0.1)"
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
focusField(args) {
|
focusField( args ) {
|
||||||
args.object.focus()
|
args.object.focus()
|
||||||
setTimeout((e) => Utils.ad.showSoftInput(args.object.android), 1)
|
setTimeout( ( e ) => Utils.ad.showSoftInput( args.object.android ), 1 )
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
if (this.text) {
|
if ( this.text ) {
|
||||||
this.category = this.text
|
this.category = localize( this.text )
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,45 +1,31 @@
|
||||||
<template>
|
<template>
|
||||||
<Page>
|
<Page>
|
||||||
<StackLayout class="dialogContainer" :class="appTheme">
|
<StackLayout class="dialogContainer" :class="appTheme">
|
||||||
<Label class="dialogTitle orkm" :text="title" />
|
<Label class="dialogTitle orkm" :text="`${title}` | L" />
|
||||||
<GridLayout rows="auto, auto" columns="*" class="actionsContainer">
|
<GridLayout rows="auto, auto" columns="*" class="actionsContainer">
|
||||||
<MDButton
|
<MDButton :rippleColor="rippleColor" :backgroundColor="backgroundColor" row="0" class="actionIcon" src="res://photo" :text="'Photo' | L" @tap="$modal.close('photo')" />
|
||||||
:rippleColor="rippleColor"
|
<MDButton :rippleColor="rippleColor" :backgroundColor="backgroundColor" row="1" class="actionIcon" src="res://detail" :text="'Recipe' | L" @tap="$modal.close('recipe')" />
|
||||||
:backgroundColor="backgroundColor"
|
|
||||||
row="0"
|
|
||||||
class="actionIcon"
|
|
||||||
src="res://photo"
|
|
||||||
text="Photo"
|
|
||||||
@tap="$modal.close('photo')"
|
|
||||||
/>
|
|
||||||
<MDButton
|
|
||||||
:rippleColor="rippleColor"
|
|
||||||
:backgroundColor="backgroundColor"
|
|
||||||
row="1"
|
|
||||||
class="actionIcon"
|
|
||||||
src="res://detail"
|
|
||||||
text="Recipe"
|
|
||||||
@tap="$modal.close('recipe')"
|
|
||||||
/>
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { Application } from "@nativescript/core"
|
import {
|
||||||
import { mapState } from "vuex"
|
Application
|
||||||
|
} from "@nativescript/core"
|
||||||
|
import {
|
||||||
|
mapState
|
||||||
|
} from "vuex"
|
||||||
export default {
|
export default {
|
||||||
props: ["title"],
|
props: [ "title" ],
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(["icon"]),
|
...mapState( [ "icon" ] ),
|
||||||
appTheme() {
|
appTheme() {
|
||||||
return Application.systemAppearance()
|
return Application.systemAppearance()
|
||||||
},
|
},
|
||||||
rippleColor() {
|
rippleColor() {
|
||||||
return this.appTheme == "light"
|
return this.appTheme == "light" ? "rgba(134,142,150,0.2)" : "rgba(206,212,218,0.1)"
|
||||||
? "rgba(134,142,150,0.2)"
|
|
||||||
: "rgba(206,212,218,0.1)"
|
|
||||||
},
|
},
|
||||||
backgroundColor() {
|
backgroundColor() {
|
||||||
return this.appTheme == "light" ? "#fff" : "#343a40"
|
return this.appTheme == "light" ? "#fff" : "#343a40"
|
||||||
|
|
206
app/i18n/en.default.json
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
{
|
||||||
|
"app.name": "EnRecipes",
|
||||||
|
"EnRecipes": "EnRecipes",
|
||||||
|
"Try Later": "Try Later",
|
||||||
|
"Favourites": "Favourites",
|
||||||
|
"Meal Planner": "Meal Planner",
|
||||||
|
"Categories": "Categories",
|
||||||
|
"DONE": "DONE",
|
||||||
|
"RENAME": "RENAME",
|
||||||
|
"Settings": "Settings",
|
||||||
|
"About": "About",
|
||||||
|
"Appetizers": "Appetizers",
|
||||||
|
"Barbecue": "Barbecue",
|
||||||
|
"Beverages": "Beverages",
|
||||||
|
"Breads": "Breads",
|
||||||
|
"Breakfast": "Breakfast",
|
||||||
|
"Desserts": "Desserts",
|
||||||
|
"Dinner": "Dinner",
|
||||||
|
"Drinks": "Drinks",
|
||||||
|
"Healthy": "Healthy",
|
||||||
|
"Lunch": "Lunch",
|
||||||
|
"Main dishes": "Main dishes",
|
||||||
|
"Meat": "Meat",
|
||||||
|
"Noodles": "Noodles",
|
||||||
|
"Pasta": "Pasta",
|
||||||
|
"Poultry": "Poultry",
|
||||||
|
"Rice": "Rice",
|
||||||
|
"Salads": "Salads",
|
||||||
|
"Sauces": "Sauces",
|
||||||
|
"Seafood": "Seafood",
|
||||||
|
"Side dishes": "Side dishes",
|
||||||
|
"Snacks": "Snacks",
|
||||||
|
"Soups": "Soups",
|
||||||
|
"Undefined": "Undefined",
|
||||||
|
"Vegan": "Vegan",
|
||||||
|
"Vegetarian": "Vegetarian",
|
||||||
|
"Serving": "Serving",
|
||||||
|
"Piece": "Piece",
|
||||||
|
"Teaspoon": "Teaspoon",
|
||||||
|
"Tablespoon": "Tablespoon",
|
||||||
|
"Fluid Ounce": "Fluid Ounce",
|
||||||
|
"Ounce": "Ounce",
|
||||||
|
"Pound": "Pound",
|
||||||
|
"Gram": "Gram",
|
||||||
|
"Kilogram": "Kilogram",
|
||||||
|
"Cup": "Cup",
|
||||||
|
"Gallon": "Gallon",
|
||||||
|
"Millilitre": "Millilitre",
|
||||||
|
"Litre": "Litre",
|
||||||
|
"Roll": "Roll",
|
||||||
|
"Patty": "Patty",
|
||||||
|
"Loaf": "Loaf",
|
||||||
|
"unit": "unit",
|
||||||
|
"Unit": "Unit",
|
||||||
|
"tsp": "tsp",
|
||||||
|
"dsp": "dsp",
|
||||||
|
"tbsp": "tbsp",
|
||||||
|
"fl oz": "fl oz",
|
||||||
|
"cup": "cup",
|
||||||
|
"pt": "pt",
|
||||||
|
"qt": "qt",
|
||||||
|
"gal": "gal",
|
||||||
|
"ml": "ml",
|
||||||
|
"l": "l",
|
||||||
|
"oz": "oz",
|
||||||
|
"lb": "lb",
|
||||||
|
"mg": "mg",
|
||||||
|
"g": "g",
|
||||||
|
"kg": "kg",
|
||||||
|
"cm": "cm",
|
||||||
|
"in": "in",
|
||||||
|
"leaf": "leaf",
|
||||||
|
"clove": "clove",
|
||||||
|
"piece": "piece",
|
||||||
|
"pinch": "pinch",
|
||||||
|
"drop": "drop",
|
||||||
|
"dozen": "dozen",
|
||||||
|
"stick": "stick",
|
||||||
|
"small": "small",
|
||||||
|
"medium": "medium",
|
||||||
|
"large": "large",
|
||||||
|
"Start adding your recipes!": "Start adding your recipes!",
|
||||||
|
"Use the plus button to add one": "Use the plus button to add one",
|
||||||
|
"Use the pencil button to add some ingredients": "Use the pencil button to add some ingredients",
|
||||||
|
"Use the pencil button to add some instructions": "Use the pencil button to add some instructions",
|
||||||
|
"Use the pencil button to add some combinations": "Use the pencil button to add some combinations",
|
||||||
|
"Use the pencil button to add some notes": "Use the pencil button to add some notes",
|
||||||
|
"All done!": "All done!",
|
||||||
|
"Recipes you mark as try later will be listed here": "Recipes you mark as try later will be listed here",
|
||||||
|
"No favourites yet": "No favourites yet",
|
||||||
|
"Recipes you mark as favourite will be listed here": "Recipes you mark as favourite will be listed here",
|
||||||
|
"Category looks empty": "Category looks empty",
|
||||||
|
"No recipes found": "No recipes found",
|
||||||
|
"Your search did not match any recipes": "Your search did not match any recipes",
|
||||||
|
"Your search did not match any recipes in this category": "Your search did not match any recipes in this category",
|
||||||
|
"Your search did not match any recipes in your favourites": "Your search did not match any recipes in your favourites",
|
||||||
|
"Your search did not match any recipes in your try later list": "Your search did not match any recipes in your try later list",
|
||||||
|
"Interface": "Interface",
|
||||||
|
"App language": "App language",
|
||||||
|
"System default": "System default",
|
||||||
|
"Theme": "Theme",
|
||||||
|
"Light": "Light",
|
||||||
|
"Dark": "Dark",
|
||||||
|
"Database": "Database",
|
||||||
|
"Export a full backup": "Export a full backup",
|
||||||
|
"Generates a zip file that contains all your data. This file can be imported back.": "Generates a zip file that contains all your data. This file can be imported back.",
|
||||||
|
"Import from backup": "Import from backup",
|
||||||
|
"Supports full backups exported by this app": "Supports full backups exported by this app",
|
||||||
|
"Version": "Version",
|
||||||
|
"View project on GitHub": "View project on GitHub",
|
||||||
|
"Join the Telegram group": "Join the Telegram group",
|
||||||
|
"for reporting issues, suggestions and feedback": "for reporting issues, suggestions and feedback",
|
||||||
|
"Author": "Author",
|
||||||
|
"Vishnu Raghav B": "Vishnu Raghav B",
|
||||||
|
"Follow on GitHub": "Follow on GitHub",
|
||||||
|
"Follow on Mastodon": "Follow on Mastodon",
|
||||||
|
"New recipe": "New recipe",
|
||||||
|
"Edit recipe": "Edit recipe",
|
||||||
|
"Title": "Title",
|
||||||
|
"Category": "Category",
|
||||||
|
"Preparation time": "Preparation time",
|
||||||
|
"Cooking time": "Cooking time",
|
||||||
|
"Yield quantity": "Yield quantity",
|
||||||
|
"Yield measured in": "Yield measured in",
|
||||||
|
"Ingredient": "Ingredient",
|
||||||
|
"Ingredients": "Ingredients",
|
||||||
|
"ADD INGREDIENT": "ADD INGREDIENT",
|
||||||
|
"Instruction": "Instruction",
|
||||||
|
"Instructions": "Instructions",
|
||||||
|
"ADD STEP": "ADD STEP",
|
||||||
|
"Combinations": "Combinations",
|
||||||
|
"ADD COMBINATION": "ADD COMBINATION",
|
||||||
|
"Note": "Note",
|
||||||
|
"Notes": "Notes",
|
||||||
|
"ADD NOTE": "ADD NOTE",
|
||||||
|
"Item": "Item",
|
||||||
|
"Step": "Step",
|
||||||
|
"Note": "Note",
|
||||||
|
"Sort by": "Sort by",
|
||||||
|
"Natural order": "Natural order",
|
||||||
|
"Duration": "Duration",
|
||||||
|
"Last modified": "Last modified",
|
||||||
|
"CANCEL": "CANCEL",
|
||||||
|
"REMOVE": "REMOVE",
|
||||||
|
"ADD": "ADD",
|
||||||
|
"Select a recipe": "Select a recipe",
|
||||||
|
"Nothing here! Add some recipes and try again.": "Nothing here! Add some recipes and try again.",
|
||||||
|
"My Healthy Recipe": "My Healthy Recipe",
|
||||||
|
"hr": "hr",
|
||||||
|
"min": "min",
|
||||||
|
"Photo": "Photo",
|
||||||
|
"Recipe": "Recipe",
|
||||||
|
"Overview": "Overview",
|
||||||
|
"Share": "Share",
|
||||||
|
"ADD NEW": "ADD NEW",
|
||||||
|
"SET": "SET",
|
||||||
|
"Restart required": "Restart required",
|
||||||
|
"RESTART": "RESTART",
|
||||||
|
"EnRecipes needs to be restarted for the theme change to take effect.": "EnRecipes needs to be restarted for the theme change to take effect.",
|
||||||
|
"EnRecipes needs to be restarted for the app language to take effect.": "EnRecipes needs to be restarted for the app language to take effect.",
|
||||||
|
"Grant permission": "Grant permission",
|
||||||
|
"EnRecipes requires storage permission in order to import your data from a previous backup.": "EnRecipes requires storage permission in order to import your data from a previous backup.",
|
||||||
|
"NOT NOW": "NOT NOW",
|
||||||
|
"CONTINUE": "CONTINUE",
|
||||||
|
"EnRecipes requires storage permission in order to backup your data to this device.": "EnRecipes requires storage permission in order to backup your data to this device.",
|
||||||
|
"Add at least one recipe to perform a backup": "Add at least one recipe to perform a backup",
|
||||||
|
"Added to Favourites": "Added to Favourites",
|
||||||
|
"Removed from Favourites": "Removed from Favourites",
|
||||||
|
"Added to Try Later": "Added to Try Later",
|
||||||
|
"Removed from Try Later": "Removed from Try Later",
|
||||||
|
"Delete recipe?": "Delete recipe?",
|
||||||
|
"DELETE": "DELETE",
|
||||||
|
"Are you sure you want to delete the recipe": "Are you sure you want to delete the recipe",
|
||||||
|
"Search": "Search",
|
||||||
|
"Rename category": "Rename category",
|
||||||
|
"Unsaved changes": "Unsaved changes",
|
||||||
|
"Are you sure you want to discard unsaved changes to this recipe?": "Are you sure you want to discard unsaved changes to this recipe?",
|
||||||
|
"DISCARD": "DISCARD",
|
||||||
|
"KEEP EDITING": "KEEP EDITING",
|
||||||
|
"Remove ingredient?": "Remove ingredient?",
|
||||||
|
"Remove instruction?": "Remove instruction?",
|
||||||
|
"Remove combination?": "Remove combination?",
|
||||||
|
"Remove note?": "Remove note?",
|
||||||
|
"New yield unit": "New yield unit",
|
||||||
|
"New category": "New category",
|
||||||
|
"Required": "Required",
|
||||||
|
"EnRecipes requires storage permission in order to set recipe photo.": "EnRecipes requires storage permission in order to set recipe photo.",
|
||||||
|
"Recipe photo": "Recipe photo",
|
||||||
|
"REPLACE PHOTO": "REPLACE PHOTO",
|
||||||
|
"Crop photo": "Crop photo",
|
||||||
|
"breakfast": "breakfast",
|
||||||
|
"lunch": "lunch",
|
||||||
|
"dinner": "dinner",
|
||||||
|
"snacks": "snacks",
|
||||||
|
"You tried this recipe:": "You tried this recipe:",
|
||||||
|
"today": "today",
|
||||||
|
"yesterday": "yesterday",
|
||||||
|
"days ago": "days ago",
|
||||||
|
"weeks ago": "weeks ago",
|
||||||
|
"months ago": "months ago",
|
||||||
|
"long time ago": "long time ago",
|
||||||
|
"Verifying...": "Verifying...",
|
||||||
|
"Import successful": "Import successful",
|
||||||
|
"Permission denied": "Permission denied",
|
||||||
|
"Shared via EnRecipes. Get it on Play Store or F-Droid.": "Shared via EnRecipes. Get it on Play Store or F-Droid."
|
||||||
|
}
|
206
app/i18n/ta.json
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
{
|
||||||
|
"app.name": "என்ரெசிபீஸ்",
|
||||||
|
"EnRecipes": "என்ரெசிபீஸ்",
|
||||||
|
"Try Later": "பின்னர் முயற்சிக்க",
|
||||||
|
"Favourites": "பிடித்தவை",
|
||||||
|
"Meal Planner": "உணவுத் திட்டம்",
|
||||||
|
"Categories": "வகைகள்",
|
||||||
|
"DONE": "முடிந்தது",
|
||||||
|
"RENAME": "மறுபெயரிடு",
|
||||||
|
"Settings": "அமைப்புகள்",
|
||||||
|
"About": "பற்றி",
|
||||||
|
"Appetizers": "பசித்தூண்டி",
|
||||||
|
"Barbecue": "பார்பிக்யூ",
|
||||||
|
"Beverages": "பானங்கள்",
|
||||||
|
"Breads": "ரொட்டிகள்",
|
||||||
|
"Breakfast": "காலை உணவு",
|
||||||
|
"Desserts": "இனிப்புகள்",
|
||||||
|
"Dinner": "இரவு உணவு",
|
||||||
|
"Drinks": "மதுபானம்",
|
||||||
|
"Healthy": "ஆரோக்கியமானவை",
|
||||||
|
"Lunch": "மதிய உணவு",
|
||||||
|
"Main dishes": "முக்கிய உணவுகள்",
|
||||||
|
"Meat": "இறைச்சி",
|
||||||
|
"Noodles": "நூடுல்ஸ்",
|
||||||
|
"Pasta": "பாஸ்தா",
|
||||||
|
"Poultry": "கோழி",
|
||||||
|
"Rice": "சோறு",
|
||||||
|
"Salads": "சாலடுகள்",
|
||||||
|
"Sauces": "சாஸ்கள்",
|
||||||
|
"Seafood": "கடல் உணவு",
|
||||||
|
"Side dishes": "தொடு கறிகள்",
|
||||||
|
"Snacks": "தின்பண்டங்கள்",
|
||||||
|
"Soups": "சூப்கள்",
|
||||||
|
"Undefined": "வரையறுக்கப்படாதவை",
|
||||||
|
"Vegan": "வேகன்",
|
||||||
|
"Vegetarian": "சைவம்",
|
||||||
|
"Serving": "கூறு",
|
||||||
|
"Piece": "துண்டு",
|
||||||
|
"Teaspoon": "டீஸ்பூன்",
|
||||||
|
"Tablespoon": "தேக்கரண்டி",
|
||||||
|
"Fluid Ounce": "திரவ அவுன்ஸ்",
|
||||||
|
"Ounce": "அவுன்ஸ்",
|
||||||
|
"Pound": "பவுண்டு",
|
||||||
|
"Gram": "கிராம்",
|
||||||
|
"Kilogram": "கிலோகிராம்",
|
||||||
|
"Cup": "கோப்பை",
|
||||||
|
"Gallon": "கேலன்",
|
||||||
|
"Millilitre": "மில்லிலிட்டர்",
|
||||||
|
"Litre": "லிட்டர்",
|
||||||
|
"Roll": "ரோல்",
|
||||||
|
"Patty": "வடை",
|
||||||
|
"Loaf": "ரொட்டித் துண்டு",
|
||||||
|
"unit": "அலகு",
|
||||||
|
"Unit": "அலகு",
|
||||||
|
"tsp": "டீஸ்பூன்",
|
||||||
|
"dsp": "இனிப்பு ஸ்பூன்",
|
||||||
|
"tbsp": "தேக்கரண்டி",
|
||||||
|
"fl oz": "திரவ அவுன்ஸ",
|
||||||
|
"cup": "கோப்பை",
|
||||||
|
"pt": "பைண்ட்",
|
||||||
|
"qt": "குவிண்ட்",
|
||||||
|
"gal": "கேலன்",
|
||||||
|
"ml": "மில்லிலிட்டர்",
|
||||||
|
"l": "லிட்டர்",
|
||||||
|
"oz": "அவுன்ஸ்",
|
||||||
|
"lb": "பவுண்டு",
|
||||||
|
"mg": "மில்லிகிராம்",
|
||||||
|
"g": "கிராம்",
|
||||||
|
"kg": "கிலோகிராம்",
|
||||||
|
"cm": "சென்டிமீட்டர்",
|
||||||
|
"in": "அங்குலம்",
|
||||||
|
"leaf": "இலை",
|
||||||
|
"clove": "பல்",
|
||||||
|
"piece": "துண்டு",
|
||||||
|
"pinch": "கிள்ளு",
|
||||||
|
"drop": "துளி",
|
||||||
|
"dozen": "டஜன்",
|
||||||
|
"stick": "குச்சி",
|
||||||
|
"small": "சிறிய",
|
||||||
|
"medium": "நடுத்தர",
|
||||||
|
"large": "பெரிய",
|
||||||
|
"Start adding your recipes!": "உங்கள் சமையல் குறிப்புகளைச் சேர்க்கத் தொடங்குங்கள்!",
|
||||||
|
"Use the plus button to add one": "ஒரு செய்முறையைச் சேர்க்க பிளஸ் பொத்தானைப் பயன்படுத்தவும்",
|
||||||
|
"Use the pencil button to add some ingredients": "தேவையான பொருட்களைச் சேர்க்க பென்சில் பொத்தானைப் பயன்படுத்தவும்",
|
||||||
|
"Use the pencil button to add some instructions": "செய்முறைகளைச் சேர்க்க பென்சில் பொத்தானைப் பயன்படுத்தவும்",
|
||||||
|
"Use the pencil button to add some combinations": "சில சேர்க்கைகளைச் சேர்க்க பென்சில் பொத்தானைப் பயன்படுத்தவும்",
|
||||||
|
"Use the pencil button to add some notes": "சில குறிப்புகளைச் சேர்க்க பென்சில் பொத்தானைப் பயன்படுத்தவும்",
|
||||||
|
"All done!": "அனைத்தும் செய்யப்பட்டுள்ளன!",
|
||||||
|
"Recipes you mark as try later will be listed here": "முயற்சிக்க வேண்டும் என நீங்கள் குறிக்கும் சமையல் குறிப்புகள் இங்கே பட்டியலிடப்படும்",
|
||||||
|
"No favourites yet": "இன்னும் பிடித்தவை எதுவும் இல்லை",
|
||||||
|
"Recipes you mark as favourite will be listed here": "நீங்கள் பிடித்ததாகக் குறிக்கும் சமையல் குறிப்புகள் இங்கே பட்டியலிடப்படும்",
|
||||||
|
"Category looks empty": "இந்த பிரிவில் எந்த சமையல் குறிப்புகளும் இல்லை",
|
||||||
|
"No recipes found": "எந்த சமையல் குறிப்புகளும் இல்லை",
|
||||||
|
"Your search did not match any recipes": "உங்கள் தேடல் எந்த சமையல் குறிப்புகளுக்கும் பொருந்தவில்லை",
|
||||||
|
"Your search did not match any recipes in this category": "உங்கள் தேடல் இந்த வகையில் எந்த சமையல் குறிப்புகளுடன் பொருந்தவில்லை",
|
||||||
|
"Your search did not match any recipes in your favourites": "உங்கள் தேடல் உங்களுக்கு பிடித்தவற்றில் எந்த சமையல் குறிப்புகளுடன் பொருந்தவில்லைை",
|
||||||
|
"Your search did not match any recipes in your try later list": "உங்கள் தேடல் நீங்கள் முயற்சிக்க வேண்டிய பட்டியலில் உள்ள எந்த சமையல் குறிப்புகளுடன் பொருந்தவில்லைை",
|
||||||
|
"Interface": "இடைமுகம்",
|
||||||
|
"App language": "பயன்பாட்டு மொழி",
|
||||||
|
"System default": "கணினி இயல்புநிலை",
|
||||||
|
"Theme": "தீம்",
|
||||||
|
"Light": "வெளிச்சம்",
|
||||||
|
"Dark": "இருள்",
|
||||||
|
"Database": "தரவுத்தளம்",
|
||||||
|
"Export a full backup": "முழு காப்புப்பிரதியை ஏற்றுமதி செய்க",
|
||||||
|
"Generates a zip file that contains all your data. This file can be imported back.": "இது உங்கள் எல்லா தரவையும் கொண்ட ஒரு ஜிப் கோப்பை உருவாக்குகிறது. இந்த கோப்பை மீண்டும் இறக்குமதி செய்யலாம்.",
|
||||||
|
"Import from backup": "காப்புப்பிரதியிலிருந்து இறக்குமதி செய்க",
|
||||||
|
"Supports full backups exported by this app": "இந்த பயன்பாட்டின் மூலம் ஏற்றுமதி செய்யப்பட்ட முழு காப்புப்பிரதிகளை ஆதரிக்கும்",
|
||||||
|
"Version": "பதிப்பு",
|
||||||
|
"View project on GitHub": "கிட்ஹப்பில் திட்டத்தைக் காண்க",
|
||||||
|
"Join the Telegram group": "டெலிகிராம் குழுவில் சேரவும்",
|
||||||
|
"for reporting issues, suggestions and feedback": "சிக்கல்கள், பரிந்துரைகள் மற்றும் கருத்துக்களைப் புகாரளிக்க",
|
||||||
|
"Author": "பயன்பாட்டு ஆசிரியர்",
|
||||||
|
"Vishnu Raghav B": "விஷ்ணு ராகவ் .பா",
|
||||||
|
"Follow on GitHub": "கிட்ஹப்பில் அவரைப் பின்தொடரவும்",
|
||||||
|
"Follow on Mastodon": "மஸ்டோடனில் அவரைப் பின்தொடரவும்",
|
||||||
|
"New recipe": "புதிய செய்முறை",
|
||||||
|
"Edit recipe": "செய்முறையைத் திருத்து",
|
||||||
|
"Title": "தலைப்பு",
|
||||||
|
"Category": "வகை",
|
||||||
|
"Preparation time": "தயாரிப்பு நேரம்",
|
||||||
|
"Cooking time": "சமைக்கும் நேரம்",
|
||||||
|
"Yield quantity": "மகசூல் அளவு",
|
||||||
|
"Yield measured in": "மகசூல் அலகு",
|
||||||
|
"Ingredient": "தேவையான பொருள்",
|
||||||
|
"Ingredients": "தேவையான பொருட்கள்",
|
||||||
|
"ADD INGREDIENT": "பொருளைச் சேர்",
|
||||||
|
"Instruction": "செய்முறை",
|
||||||
|
"Instructions": "செய்முறைகள்",
|
||||||
|
"ADD STEP": "செய்முறையைச் சேர்",
|
||||||
|
"Combinations": "சேர்க்கைகள்",
|
||||||
|
"ADD COMBINATION": "சேர்க்கையைச் சேர்",
|
||||||
|
"Note": "குறிப்பு",
|
||||||
|
"Notes": "குறிப்புகள்",
|
||||||
|
"ADD NOTE": "குறிப்பைச் சேர்",
|
||||||
|
"Item": "பொருள்",
|
||||||
|
"Step": "செயஂமுறை",
|
||||||
|
"Note": "குறிப்பு",
|
||||||
|
"Sort by": "வரிசை விதி",
|
||||||
|
"Natural order": "இயற்கை வரிசை",
|
||||||
|
"Duration": "நேரம்",
|
||||||
|
"Last modified": "கடைசியாக மாற்றப்பட்டது",
|
||||||
|
"CANCEL": "ரத்துசெய்",
|
||||||
|
"REMOVE": "அகற்று",
|
||||||
|
"ADD": "சேர்",
|
||||||
|
"Select a recipe": "ஒரு செய்முறையைத் தேர்ந்தெடுக்கவும்",
|
||||||
|
"Nothing here! Add some recipes and try again.": "இங்கு எதுவுமில்லை! சில சமையல் வகைகளைச் சேர்த்து மீண்டும் முயற்சிக்கவும்.",
|
||||||
|
"My Healthy Recipe": "எனது ஆரோக்கியமான செய்முறை",
|
||||||
|
"hr": "மணி",
|
||||||
|
"min": "நிமிடம்",
|
||||||
|
"Photo": "புகைப்படம்",
|
||||||
|
"Recipe": "செய்முறை",
|
||||||
|
"Overview": "கண்ணோட்டம்",
|
||||||
|
"Share": "பகிர்",
|
||||||
|
"ADD NEW": "புதியனவற்றை சேர்",
|
||||||
|
"SET": "அமை",
|
||||||
|
"Restart required": "மறுதொடக்கம் தேவை",
|
||||||
|
"RESTART": "மறுதொடக்கம்",
|
||||||
|
"EnRecipes needs to be restarted for the theme change to take effect.": "தீம் மாற்றம் நடைமுறைக்கு வருவதற்கு என்ரெசிபீஸ் ஐ மீண்டும் தொடங்க வேண்டும்.",
|
||||||
|
"EnRecipes needs to be restarted for the app language to take effect.": "பயன்பாட்டு மொழி நடைமுறைக்கு வருவதற்கு என்ரெசிபீஸ் ஐ மீண்டும் தொடங்க வேண்டும்.",
|
||||||
|
"Grant permission": "அனுமதி வழங்கவும்",
|
||||||
|
"EnRecipes requires storage permission in order to import your data from a previous backup.": "முந்தைய காப்புப்பிரதியிலிருந்து உங்கள் தரவை இறக்குமதி செய்ய என்ரெசிபீஸ்க்கு சேமிப்பு அனுமதி தேவைப்படுகிறது.",
|
||||||
|
"NOT NOW": "இப்போது இல்லை",
|
||||||
|
"CONTINUE": "தொடர்",
|
||||||
|
"EnRecipes requires storage permission in order to backup your data to this device.": "இந்தச் சாதனத்தில் உங்கள் தரவை காப்புப் பிரதி எடுக்க என்ரெசிபீஸ்க்கு சேமிப்பக அனுமதி தேவைப்படுகிறது.",
|
||||||
|
"Add at least one recipe to perform a backup": "காப்புப்பிரதி செய்ய குறைந்தபட்சம் ஒரு செய்முறையாவது சேர்க்கவும்",
|
||||||
|
"Added to Favourites": "பிடித்தவையில் சேர்க்கப்பட்டது",
|
||||||
|
"Removed from Favourites": "பிடித்தவற்றிலிருந்து அகற்றப்பட்டது",
|
||||||
|
"Added to Try Later": "பின்னர் முயற்சிக்க சேர்க்கப்பட்டது",
|
||||||
|
"Removed from Try Later": "பின்னர் முயற்சிப்பதில் இருந்து நீக்கப்பட்டது",
|
||||||
|
"Delete recipe?": "செய்முறையை நீக்கவா?",
|
||||||
|
"DELETE": "நீக்கு",
|
||||||
|
"Are you sure you want to delete the recipe": "இந்த செய்முறையை நீக்க விரும்புகிறீர்களா",
|
||||||
|
"Search": "தேடு",
|
||||||
|
"Rename category": "வகையை மறுபெயரிடுங்கள்",
|
||||||
|
"Unsaved changes": "சேமிக்கப்படாத மாற்றங்கள்",
|
||||||
|
"Are you sure you want to discard unsaved changes to this recipe?": "இந்த செய்முறையில் சேமிக்கப்படாத மாற்றங்களை நிராகரிக்க விரும்புகிறீர்களா?",
|
||||||
|
"DISCARD": "நிராகரி",
|
||||||
|
"KEEP EDITING": "தொடர்ந்து திருத்து",
|
||||||
|
"Remove ingredient?": "பொருளை அகற்றவா?",
|
||||||
|
"Remove instruction?": "செய்முறையை அகற்றவா?",
|
||||||
|
"Remove combination?": "சேர்க்கையை அகற்றவா?",
|
||||||
|
"Remove note?": "குறிப்பை அகற்றவா?",
|
||||||
|
"New yield unit": "புதிய மகசூல் அலகு",
|
||||||
|
"New category": "புதிய வகை",
|
||||||
|
"Required": "தேவையான",
|
||||||
|
"EnRecipes requires storage permission in order to set recipe photo.": "செய்முறை புகைப்படத்தை அமைக்க என்ரெசிபீஸ்க்கு சேமிப்பு அனுமதி தேவை.",
|
||||||
|
"Recipe photo": "செய்முறை புகைப்படம்",
|
||||||
|
"REPLACE PHOTO": "புகைப்படத்தை மாற்றவும்",
|
||||||
|
"Crop photo": "படத்தை வெட்டு",
|
||||||
|
"breakfast": "காலை உணவு",
|
||||||
|
"lunch": "மதிய உணவு",
|
||||||
|
"dinner": "இரவு உணவு",
|
||||||
|
"snacks": "சிற்றிடை உணவு",
|
||||||
|
"You tried this recipe:": "இந்த செய்முறையை முயற்சித்தீர்கள்:",
|
||||||
|
"today": "இன்று",
|
||||||
|
"yesterday": "நேற்று",
|
||||||
|
"days ago": "நாட்களுக்கு முன்பு",
|
||||||
|
"weeks ago": "வாரங்களுக்கு முன்பு",
|
||||||
|
"months ago": "மாதங்களுக்கு முன்பு",
|
||||||
|
"long time ago": "வெகுகாலத்திற்கு முன்பு",
|
||||||
|
"Verifying...": "சரிபார்க்கிறது...",
|
||||||
|
"Import successful": "வெற்றிகரமாக இறக்குமதி செய்யப்பட்டது",
|
||||||
|
"Permission denied": "அனுமதி மறுக்கப்பட்டது",
|
||||||
|
"Shared via EnRecipes. Get it on Play Store or F-Droid.": "என்ரெசிபீஸ் வழியாக பகிரப்பட்டது. அதை ப்ளே ஸ்டோர் அல்லது எஃப்-டிரயோடு இருந்து பெறுங்கள்."
|
||||||
|
}
|
18
app/main.js
|
@ -1,3 +1,16 @@
|
||||||
|
import {
|
||||||
|
localize,
|
||||||
|
androidLaunchEventLocalizationHandler
|
||||||
|
} from '@nativescript/localize'
|
||||||
|
import {
|
||||||
|
on,
|
||||||
|
launchEvent
|
||||||
|
} from '@nativescript/core/application';
|
||||||
|
on(launchEvent, (args) => {
|
||||||
|
if (args.android) {
|
||||||
|
androidLaunchEventLocalizationHandler();
|
||||||
|
}
|
||||||
|
})
|
||||||
import Vue from "nativescript-vue"
|
import Vue from "nativescript-vue"
|
||||||
import App from "./components/App"
|
import App from "./components/App"
|
||||||
import store from "./store"
|
import store from "./store"
|
||||||
|
@ -26,7 +39,9 @@ Vue.use(CalendarView)
|
||||||
import RadSideDrawer from "nativescript-ui-sidedrawer/vue"
|
import RadSideDrawer from "nativescript-ui-sidedrawer/vue"
|
||||||
Vue.use(RadSideDrawer)
|
Vue.use(RadSideDrawer)
|
||||||
|
|
||||||
import { CheckBox } from "@nstudio/nativescript-checkbox"
|
import {
|
||||||
|
CheckBox
|
||||||
|
} from "@nstudio/nativescript-checkbox"
|
||||||
Vue.registerElement("CheckBox", () => CheckBox, {
|
Vue.registerElement("CheckBox", () => CheckBox, {
|
||||||
model: {
|
model: {
|
||||||
prop: "checked",
|
prop: "checked",
|
||||||
|
@ -35,6 +50,7 @@ Vue.registerElement("CheckBox", () => CheckBox, {
|
||||||
})
|
})
|
||||||
|
|
||||||
Vue.config.silent = TNS_ENV === "production"
|
Vue.config.silent = TNS_ENV === "production"
|
||||||
|
Vue.filter('L', localize)
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
store,
|
store,
|
||||||
|
|
|
@ -15,17 +15,22 @@
|
||||||
|
|
||||||
android {
|
android {
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
versionCode 2
|
versionCode 3
|
||||||
versionName '1.0.1'
|
versionName '1.1.2'
|
||||||
applicationId 'com.vishnuraghav.enrecipes'
|
applicationId 'com.vishnuraghav.enrecipes'
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
generatedDensities = []
|
generatedDensities = []
|
||||||
// ndk {
|
ndk {
|
||||||
// abiFilters.clear()
|
abiFilters.clear()
|
||||||
// abiFilters.addAll(['x86','armeabi-v7a','arm64-v8a'])
|
abiFilters.addAll(['x86','armeabi-v7a','arm64-v8a'])
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
aaptOptions {
|
aaptOptions {
|
||||||
additionalParameters "--no-version-vectors"
|
additionalParameters "--no-version-vectors"
|
||||||
}
|
}
|
||||||
|
// bundle {
|
||||||
|
// language {
|
||||||
|
// enableSplit = false
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 687 B After Width: | Height: | Size: 687 B |
Before Width: | Height: | Size: 567 B After Width: | Height: | Size: 567 B |
Before Width: | Height: | Size: 339 B After Width: | Height: | Size: 339 B |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 517 B After Width: | Height: | Size: 517 B |
Before Width: | Height: | Size: 197 B After Width: | Height: | Size: 197 B |
Before Width: | Height: | Size: 488 B After Width: | Height: | Size: 488 B |
Before Width: | Height: | Size: 390 B After Width: | Height: | Size: 390 B |
Before Width: | Height: | Size: 336 B After Width: | Height: | Size: 336 B |
Before Width: | Height: | Size: 229 B After Width: | Height: | Size: 229 B |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 302 B After Width: | Height: | Size: 302 B |
Before Width: | Height: | Size: 173 B After Width: | Height: | Size: 173 B |
Before Width: | Height: | Size: 303 B After Width: | Height: | Size: 303 B |
Before Width: | Height: | Size: 345 B After Width: | Height: | Size: 345 B |
Before Width: | Height: | Size: 324 B After Width: | Height: | Size: 324 B |
Before Width: | Height: | Size: 198 B After Width: | Height: | Size: 198 B |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 300 B After Width: | Height: | Size: 300 B |
Before Width: | Height: | Size: 161 B After Width: | Height: | Size: 161 B |
Before Width: | Height: | Size: 363 B After Width: | Height: | Size: 363 B |
Before Width: | Height: | Size: 626 B After Width: | Height: | Size: 626 B |
Before Width: | Height: | Size: 547 B After Width: | Height: | Size: 547 B |
Before Width: | Height: | Size: 266 B After Width: | Height: | Size: 266 B |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 437 B After Width: | Height: | Size: 437 B |
Before Width: | Height: | Size: 165 B After Width: | Height: | Size: 165 B |
Before Width: | Height: | Size: 552 B After Width: | Height: | Size: 552 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 969 B After Width: | Height: | Size: 969 B |
Before Width: | Height: | Size: 434 B After Width: | Height: | Size: 434 B |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 797 B After Width: | Height: | Size: 797 B |
Before Width: | Height: | Size: 165 B After Width: | Height: | Size: 165 B |
Before Width: | Height: | Size: 979 B After Width: | Height: | Size: 979 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 818 B After Width: | Height: | Size: 818 B |
Before Width: | Height: | Size: 449 B After Width: | Height: | Size: 449 B |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 697 B After Width: | Height: | Size: 697 B |
Before Width: | Height: | Size: 171 B After Width: | Height: | Size: 171 B |
Before Width: | Height: | Size: 1,020 B After Width: | Height: | Size: 1,020 B |
208
app/resources/Android/src/main/res/values-ta/strings.xml
Normal file
|
@ -0,0 +1,208 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="_Shared_via_EnRecipes__Get_it_on_Play_Store_or_F_Droid__Z2oTOK1">"என்ரெசிபீஸ் வழியாக பகிரப்பட்டது. அதை ப்ளே ஸ்டோர் அல்லது எஃப்-டிரயோடு இருந்து பெறுங்கள்."</string>
|
||||||
|
<string name="_Permission_denied_Z7wlWK">"அனுமதி மறுக்கப்பட்டது"</string>
|
||||||
|
<string name="_Import_successful_2bLM3e">"வெற்றிகரமாக இறக்குமதி செய்யப்பட்டது"</string>
|
||||||
|
<string name="_Verifying____cS102">"சரிபார்க்கிறது..."</string>
|
||||||
|
<string name="_long_time_ago_1nwlFA">"வெகுகாலத்திற்கு முன்பு"</string>
|
||||||
|
<string name="_months_ago_Z1TsskA">"மாதங்களுக்கு முன்பு"</string>
|
||||||
|
<string name="_weeks_ago_Z2sT1GA">"வாரங்களுக்கு முன்பு"</string>
|
||||||
|
<string name="_days_ago_2iCYkm">"நாட்களுக்கு முன்பு"</string>
|
||||||
|
<string name="yesterday">"நேற்று"</string>
|
||||||
|
<string name="today">"இன்று"</string>
|
||||||
|
<string name="_You_tried_this_recipe__ZUJOl3">"இந்த செய்முறையை முயற்சித்தீர்கள்:"</string>
|
||||||
|
<string name="snacks">"சிற்றிடை உணவு"</string>
|
||||||
|
<string name="dinner">"இரவு உணவு"</string>
|
||||||
|
<string name="lunch">"மதிய உணவு"</string>
|
||||||
|
<string name="breakfast">"காலை உணவு"</string>
|
||||||
|
<string name="_Crop_photo_1VL04J">"படத்தை வெட்டு"</string>
|
||||||
|
<string name="_REPLACE_PHOTO_ZLHhwH">"புகைப்படத்தை மாற்றவும்"</string>
|
||||||
|
<string name="_Recipe_photo_eqm9B">"செய்முறை புகைப்படம்"</string>
|
||||||
|
<string name="_EnRecipes_requires_storage_permission_in_order_to_set_recipe_photo__23OnNT">"செய்முறை புகைப்படத்தை அமைக்க என்ரெசிபீஸ்க்கு சேமிப்பு அனுமதி தேவை."</string>
|
||||||
|
<string name="Required">"தேவையான"</string>
|
||||||
|
<string name="_New_category_Weg73">"புதிய வகை"</string>
|
||||||
|
<string name="_New_yield_unit_1Oevd2">"புதிய மகசூல் அலகு"</string>
|
||||||
|
<string name="_Remove_note__2wyMVE">"குறிப்பை அகற்றவா?"</string>
|
||||||
|
<string name="_Remove_combination__1dr2LS">"சேர்க்கையை அகற்றவா?"</string>
|
||||||
|
<string name="_Remove_instruction__vkJfi">"செய்முறையை அகற்றவா?"</string>
|
||||||
|
<string name="_Remove_ingredient__2puvMO">"பொருளை அகற்றவா?"</string>
|
||||||
|
<string name="_KEEP_EDITING_1o9uy3">"தொடர்ந்து திருத்து"</string>
|
||||||
|
<string name="DISCARD">"நிராகரி"</string>
|
||||||
|
<string name="_Are_you_sure_you_want_to_discard_unsaved_changes_to_this_recipe__Z1G7sVC">"இந்த செய்முறையில் சேமிக்கப்படாத மாற்றங்களை நிராகரிக்க விரும்புகிறீர்களா?"</string>
|
||||||
|
<string name="_Unsaved_changes_9fqb4">"சேமிக்கப்படாத மாற்றங்கள்"</string>
|
||||||
|
<string name="_Rename_category_Z1WzCco">"வகையை மறுபெயரிடுங்கள்"</string>
|
||||||
|
<string name="Search">"தேடு"</string>
|
||||||
|
<string name="_Are_you_sure_you_want_to_delete_the_recipe_29DH9w">"இந்த செய்முறையை நீக்க விரும்புகிறீர்களா"</string>
|
||||||
|
<string name="DELETE">"நீக்கு"</string>
|
||||||
|
<string name="_Delete_recipe__Z2tMYtE">"செய்முறையை நீக்கவா?"</string>
|
||||||
|
<string name="_Removed_from_Try_Later_1h5Bkp">"பின்னர் முயற்சிப்பதில் இருந்து நீக்கப்பட்டது"</string>
|
||||||
|
<string name="_Added_to_Try_Later_Z1gaF37">"பின்னர் முயற்சிக்க சேர்க்கப்பட்டது"</string>
|
||||||
|
<string name="_Removed_from_Favourites_Z5k7LR">"பிடித்தவற்றிலிருந்து அகற்றப்பட்டது"</string>
|
||||||
|
<string name="_Added_to_Favourites_2mzllO">"பிடித்தவையில் சேர்க்கப்பட்டது"</string>
|
||||||
|
<string name="_Add_at_least_one_recipe_to_perform_a_backup_17xYaH">"காப்புப்பிரதி செய்ய குறைந்தபட்சம் ஒரு செய்முறையாவது சேர்க்கவும்"</string>
|
||||||
|
<string name="_EnRecipes_requires_storage_permission_in_order_to_backup_your_data_to_this_device__2cbvIq">"இந்தச் சாதனத்தில் உங்கள் தரவை காப்புப் பிரதி எடுக்க என்ரெசிபீஸ்க்கு சேமிப்பக அனுமதி தேவைப்படுகிறது."</string>
|
||||||
|
<string name="CONTINUE">"தொடர்"</string>
|
||||||
|
<string name="_NOT_NOW_Z1HD7qX">"இப்போது இல்லை"</string>
|
||||||
|
<string name="_EnRecipes_requires_storage_permission_in_order_to_import_your_data_from_a_previous_backup__1CKjb7">"முந்தைய காப்புப்பிரதியிலிருந்து உங்கள் தரவை இறக்குமதி செய்ய என்ரெசிபீஸ்க்கு சேமிப்பு அனுமதி தேவைப்படுகிறது."</string>
|
||||||
|
<string name="_Grant_permission_Z1UQBuh">"அனுமதி வழங்கவும்"</string>
|
||||||
|
<string name="_EnRecipes_needs_to_be_restarted_for_the_app_language_to_take_effect__ZWGUtY">"பயன்பாட்டு மொழி நடைமுறைக்கு வருவதற்கு என்ரெசிபீஸ் ஐ மீண்டும் தொடங்க வேண்டும்."</string>
|
||||||
|
<string name="_EnRecipes_needs_to_be_restarted_for_the_theme_change_to_take_effect__2kU319">"தீம் மாற்றம் நடைமுறைக்கு வருவதற்கு என்ரெசிபீஸ் ஐ மீண்டும் தொடங்க வேண்டும்."</string>
|
||||||
|
<string name="RESTART">"மறுதொடக்கம்"</string>
|
||||||
|
<string name="_Restart_required_Z22YINL">"மறுதொடக்கம் தேவை"</string>
|
||||||
|
<string name="SET">"அமை"</string>
|
||||||
|
<string name="_ADD_NEW_Zv8FjM">"புதியனவற்றை சேர்"</string>
|
||||||
|
<string name="Share">"பகிர்"</string>
|
||||||
|
<string name="Overview">"கண்ணோட்டம்"</string>
|
||||||
|
<string name="Recipe">"செய்முறை"</string>
|
||||||
|
<string name="Photo">"புகைப்படம்"</string>
|
||||||
|
<string name="min">"நிமிடம்"</string>
|
||||||
|
<string name="hr">"மணி"</string>
|
||||||
|
<string name="_My_Healthy_Recipe_Z1EqB8f">"எனது ஆரோக்கியமான செய்முறை"</string>
|
||||||
|
<string name="_Nothing_here__Add_some_recipes_and_try_again__Z25A7Q">"இங்கு எதுவுமில்லை! சில சமையல் வகைகளைச் சேர்த்து மீண்டும் முயற்சிக்கவும்."</string>
|
||||||
|
<string name="_Select_a_recipe_2lL8x2">"ஒரு செய்முறையைத் தேர்ந்தெடுக்கவும்"</string>
|
||||||
|
<string name="ADD">"சேர்"</string>
|
||||||
|
<string name="REMOVE">"அகற்று"</string>
|
||||||
|
<string name="CANCEL">"ரத்துசெய்"</string>
|
||||||
|
<string name="_Last_modified_Z1yBAS3">"கடைசியாக மாற்றப்பட்டது"</string>
|
||||||
|
<string name="Duration">"நேரம்"</string>
|
||||||
|
<string name="_Natural_order_Z1O8On5">"இயற்கை வரிசை"</string>
|
||||||
|
<string name="_Sort_by_Zq01TF">"வரிசை விதி"</string>
|
||||||
|
<string name="Step">"செயஂமுறை"</string>
|
||||||
|
<string name="Item">"பொருள்"</string>
|
||||||
|
<string name="_ADD_NOTE_ZyNw1r">"குறிப்பைச் சேர்"</string>
|
||||||
|
<string name="Notes">"குறிப்புகள்"</string>
|
||||||
|
<string name="Note">"குறிப்பு"</string>
|
||||||
|
<string name="_ADD_COMBINATION_2q9HWq">"சேர்க்கையைச் சேர்"</string>
|
||||||
|
<string name="Combinations">"சேர்க்கைகள்"</string>
|
||||||
|
<string name="_ADD_STEP_ZyMPOe">"செய்முறையைச் சேர்"</string>
|
||||||
|
<string name="Instructions">"செய்முறைகள்"</string>
|
||||||
|
<string name="Instruction">"செய்முறை"</string>
|
||||||
|
<string name="_ADD_INGREDIENT_29sSLU">"பொருளைச் சேர்"</string>
|
||||||
|
<string name="Ingredients">"தேவையான பொருட்கள்"</string>
|
||||||
|
<string name="Ingredient">"தேவையான பொருள்"</string>
|
||||||
|
<string name="_Yield_measured_in_2OoRT">"மகசூல் அலகு"</string>
|
||||||
|
<string name="_Yield_quantity_ZHx3jw">"மகசூல் அளவு"</string>
|
||||||
|
<string name="_Cooking_time_2w2fEw">"சமைக்கும் நேரம்"</string>
|
||||||
|
<string name="_Preparation_time_15BfxT">"தயாரிப்பு நேரம்"</string>
|
||||||
|
<string name="Category">"வகை"</string>
|
||||||
|
<string name="Title">"தலைப்பு"</string>
|
||||||
|
<string name="_Edit_recipe_ZPvwDP">"செய்முறையைத் திருத்து"</string>
|
||||||
|
<string name="_New_recipe_Z1Y2YKJ">"புதிய செய்முறை"</string>
|
||||||
|
<string name="_Follow_on_Mastodon_Z1v6e4V">"மஸ்டோடனில் அவரைப் பின்தொடரவும்"</string>
|
||||||
|
<string name="_Follow_on_GitHub_Z1GjptH">"கிட்ஹப்பில் அவரைப் பின்தொடரவும்"</string>
|
||||||
|
<string name="_Vishnu_Raghav_B_1qnRnC">"விஷ்ணு ராகவ் .பா"</string>
|
||||||
|
<string name="Author">"பயன்பாட்டு ஆசிரியர்"</string>
|
||||||
|
<string name="_for_reporting_issues__suggestions_and_feedback_Z1JUmyE">"சிக்கல்கள், பரிந்துரைகள் மற்றும் கருத்துக்களைப் புகாரளிக்க"</string>
|
||||||
|
<string name="_Join_the_Telegram_group_ZAXQgc">"டெலிகிராம் குழுவில் சேரவும்"</string>
|
||||||
|
<string name="_View_project_on_GitHub_1hrJ0U">"கிட்ஹப்பில் திட்டத்தைக் காண்க"</string>
|
||||||
|
<string name="Version">"பதிப்பு"</string>
|
||||||
|
<string name="_Supports_full_backups_exported_by_this_app_ZYs4f2">"இந்த பயன்பாட்டின் மூலம் ஏற்றுமதி செய்யப்பட்ட முழு காப்புப்பிரதிகளை ஆதரிக்கும்"</string>
|
||||||
|
<string name="_Import_from_backup_Z28HsC0">"காப்புப்பிரதியிலிருந்து இறக்குமதி செய்க"</string>
|
||||||
|
<string name="_Generates_a_zip_file_that_contains_all_your_data__This_file_can_be_imported_back__Z19m3xY">"இது உங்கள் எல்லா தரவையும் கொண்ட ஒரு ஜிப் கோப்பை உருவாக்குகிறது. இந்த கோப்பை மீண்டும் இறக்குமதி செய்யலாம்."</string>
|
||||||
|
<string name="_Export_a_full_backup_TJfra">"முழு காப்புப்பிரதியை ஏற்றுமதி செய்க"</string>
|
||||||
|
<string name="Database">"தரவுத்தளம்"</string>
|
||||||
|
<string name="Dark">"இருள்"</string>
|
||||||
|
<string name="Light">"வெளிச்சம்"</string>
|
||||||
|
<string name="Theme">"தீம்"</string>
|
||||||
|
<string name="_System_default_Z1jruVS">"கணினி இயல்புநிலை"</string>
|
||||||
|
<string name="_App_language_DzFsk">"பயன்பாட்டு மொழி"</string>
|
||||||
|
<string name="Interface">"இடைமுகம்"</string>
|
||||||
|
<string name="_Your_search_did_not_match_any_recipes_in_your_try_later_list_Z2wWbA1">"உங்கள் தேடல் நீங்கள் முயற்சிக்க வேண்டிய பட்டியலில் உள்ள எந்த சமையல் குறிப்புகளுடன் பொருந்தவில்லைை"</string>
|
||||||
|
<string name="_Your_search_did_not_match_any_recipes_in_your_favourites_1ylvHN">"உங்கள் தேடல் உங்களுக்கு பிடித்தவற்றில் எந்த சமையல் குறிப்புகளுடன் பொருந்தவில்லைை"</string>
|
||||||
|
<string name="_Your_search_did_not_match_any_recipes_in_this_category_P7J4V">"உங்கள் தேடல் இந்த வகையில் எந்த சமையல் குறிப்புகளுடன் பொருந்தவில்லை"</string>
|
||||||
|
<string name="_Your_search_did_not_match_any_recipes_Z1eppHH">"உங்கள் தேடல் எந்த சமையல் குறிப்புகளுக்கும் பொருந்தவில்லை"</string>
|
||||||
|
<string name="_No_recipes_found_Z125IxD">"எந்த சமையல் குறிப்புகளும் இல்லை"</string>
|
||||||
|
<string name="_Category_looks_empty_ZAK5qU">"இந்த பிரிவில் எந்த சமையல் குறிப்புகளும் இல்லை"</string>
|
||||||
|
<string name="_Recipes_you_mark_as_favourite_will_be_listed_here_Z1iIHgY">"நீங்கள் பிடித்ததாகக் குறிக்கும் சமையல் குறிப்புகள் இங்கே பட்டியலிடப்படும்"</string>
|
||||||
|
<string name="_No_favourites_yet_aPSoG">"இன்னும் பிடித்தவை எதுவும் இல்லை"</string>
|
||||||
|
<string name="_Recipes_you_mark_as_try_later_will_be_listed_here_Z1ITwPV">"முயற்சிக்க வேண்டும் என நீங்கள் குறிக்கும் சமையல் குறிப்புகள் இங்கே பட்டியலிடப்படும்"</string>
|
||||||
|
<string name="_All_done__72KYl">"அனைத்தும் செய்யப்பட்டுள்ளன!"</string>
|
||||||
|
<string name="_Use_the_pencil_button_to_add_some_notes_Z1wyyeb">"சில குறிப்புகளைச் சேர்க்க பென்சில் பொத்தானைப் பயன்படுத்தவும்"</string>
|
||||||
|
<string name="_Use_the_pencil_button_to_add_some_combinations_6NhFS">"சில சேர்க்கைகளைச் சேர்க்க பென்சில் பொத்தானைப் பயன்படுத்தவும்"</string>
|
||||||
|
<string name="_Use_the_pencil_button_to_add_some_instructions_ZAi0PH">"செய்முறைகளைச் சேர்க்க பென்சில் பொத்தானைப் பயன்படுத்தவும்"</string>
|
||||||
|
<string name="_Use_the_pencil_button_to_add_some_ingredients_Z1xOX8S">"தேவையான பொருட்களைச் சேர்க்க பென்சில் பொத்தானைப் பயன்படுத்தவும்"</string>
|
||||||
|
<string name="_Use_the_plus_button_to_add_one_1h20ms">"ஒரு செய்முறையைச் சேர்க்க பிளஸ் பொத்தானைப் பயன்படுத்தவும்"</string>
|
||||||
|
<string name="_Start_adding_your_recipes__rwnVV">"உங்கள் சமையல் குறிப்புகளைச் சேர்க்கத் தொடங்குங்கள்!"</string>
|
||||||
|
<string name="large">"பெரிய"</string>
|
||||||
|
<string name="medium">"நடுத்தர"</string>
|
||||||
|
<string name="small">"சிறிய"</string>
|
||||||
|
<string name="stick">"குச்சி"</string>
|
||||||
|
<string name="dozen">"டஜன்"</string>
|
||||||
|
<string name="drop">"துளி"</string>
|
||||||
|
<string name="pinch">"கிள்ளு"</string>
|
||||||
|
<string name="piece">"துண்டு"</string>
|
||||||
|
<string name="clove">"பல்"</string>
|
||||||
|
<string name="leaf">"இலை"</string>
|
||||||
|
<string name="in">"அங்குலம்"</string>
|
||||||
|
<string name="cm">"சென்டிமீட்டர்"</string>
|
||||||
|
<string name="kg">"கிலோகிராம்"</string>
|
||||||
|
<string name="g">"கிராம்"</string>
|
||||||
|
<string name="mg">"மில்லிகிராம்"</string>
|
||||||
|
<string name="lb">"பவுண்டு"</string>
|
||||||
|
<string name="oz">"அவுன்ஸ்"</string>
|
||||||
|
<string name="l">"லிட்டர்"</string>
|
||||||
|
<string name="ml">"மில்லிலிட்டர்"</string>
|
||||||
|
<string name="gal">"கேலன்"</string>
|
||||||
|
<string name="qt">"குவிண்ட்"</string>
|
||||||
|
<string name="pt">"பைண்ட்"</string>
|
||||||
|
<string name="cup">"கோப்பை"</string>
|
||||||
|
<string name="_fl_oz_72kqu">"திரவ அவுன்ஸ"</string>
|
||||||
|
<string name="tbsp">"தேக்கரண்டி"</string>
|
||||||
|
<string name="dsp">"இனிப்பு ஸ்பூன்"</string>
|
||||||
|
<string name="tsp">"டீஸ்பூன்"</string>
|
||||||
|
<string name="Unit">"அலகு"</string>
|
||||||
|
<string name="unit">"அலகு"</string>
|
||||||
|
<string name="Loaf">"ரொட்டித் துண்டு"</string>
|
||||||
|
<string name="Patty">"வடை"</string>
|
||||||
|
<string name="Roll">"ரோல்"</string>
|
||||||
|
<string name="Litre">"லிட்டர்"</string>
|
||||||
|
<string name="Millilitre">"மில்லிலிட்டர்"</string>
|
||||||
|
<string name="Gallon">"கேலன்"</string>
|
||||||
|
<string name="Cup">"கோப்பை"</string>
|
||||||
|
<string name="Kilogram">"கிலோகிராம்"</string>
|
||||||
|
<string name="Gram">"கிராம்"</string>
|
||||||
|
<string name="Pound">"பவுண்டு"</string>
|
||||||
|
<string name="Ounce">"அவுன்ஸ்"</string>
|
||||||
|
<string name="_Fluid_Ounce_bd10L">"திரவ அவுன்ஸ்"</string>
|
||||||
|
<string name="Tablespoon">"தேக்கரண்டி"</string>
|
||||||
|
<string name="Teaspoon">"டீஸ்பூன்"</string>
|
||||||
|
<string name="Piece">"துண்டு"</string>
|
||||||
|
<string name="Serving">"கூறு"</string>
|
||||||
|
<string name="Vegetarian">"சைவம்"</string>
|
||||||
|
<string name="Vegan">"வேகன்"</string>
|
||||||
|
<string name="Undefined">"வரையறுக்கப்படாதவை"</string>
|
||||||
|
<string name="Soups">"சூப்கள்"</string>
|
||||||
|
<string name="Snacks">"தின்பண்டங்கள்"</string>
|
||||||
|
<string name="_Side_dishes_Z1Et4Vg">"தொடு கறிகள்"</string>
|
||||||
|
<string name="Seafood">"கடல் உணவு"</string>
|
||||||
|
<string name="Sauces">"சாஸ்கள்"</string>
|
||||||
|
<string name="Salads">"சாலடுகள்"</string>
|
||||||
|
<string name="Rice">"சோறு"</string>
|
||||||
|
<string name="Poultry">"கோழி"</string>
|
||||||
|
<string name="Pasta">"பாஸ்தா"</string>
|
||||||
|
<string name="Noodles">"நூடுல்ஸ்"</string>
|
||||||
|
<string name="Meat">"இறைச்சி"</string>
|
||||||
|
<string name="_Main_dishes_u6RGQ">"முக்கிய உணவுகள்"</string>
|
||||||
|
<string name="Lunch">"மதிய உணவு"</string>
|
||||||
|
<string name="Healthy">"ஆரோக்கியமானவை"</string>
|
||||||
|
<string name="Drinks">"மதுபானம்"</string>
|
||||||
|
<string name="Dinner">"இரவு உணவு"</string>
|
||||||
|
<string name="Desserts">"இனிப்புகள்"</string>
|
||||||
|
<string name="Breakfast">"காலை உணவு"</string>
|
||||||
|
<string name="Breads">"ரொட்டிகள்"</string>
|
||||||
|
<string name="Beverages">"பானங்கள்"</string>
|
||||||
|
<string name="Barbecue">"பார்பிக்யூ"</string>
|
||||||
|
<string name="Appetizers">"பசித்தூண்டி"</string>
|
||||||
|
<string name="About">"பற்றி"</string>
|
||||||
|
<string name="Settings">"அமைப்புகள்"</string>
|
||||||
|
<string name="RENAME">"மறுபெயரிடு"</string>
|
||||||
|
<string name="DONE">"முடிந்தது"</string>
|
||||||
|
<string name="Categories">"வகைகள்"</string>
|
||||||
|
<string name="_Meal_Planner_2aq4oj">"உணவுத் திட்டம்"</string>
|
||||||
|
<string name="Favourites">"பிடித்தவை"</string>
|
||||||
|
<string name="_Try_Later_If7PG">"பின்னர் முயற்சிக்க"</string>
|
||||||
|
<string name="EnRecipes">"என்ரெசிபீஸ்"</string>
|
||||||
|
<string name="_app_name_1k3Sbz">"என்ரெசிபீஸ்"</string>
|
||||||
|
<string name="app_name">"என்ரெசிபீஸ்"</string>
|
||||||
|
<string name="title_activity_kimera">"என்ரெசிபீஸ்"</string>
|
||||||
|
</resources>
|
208
app/resources/Android/src/main/res/values/strings.xml
Normal file
|
@ -0,0 +1,208 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="_Shared_via_EnRecipes__Get_it_on_Play_Store_or_F_Droid__Z2oTOK1">"Shared via EnRecipes. Get it on Play Store or F-Droid."</string>
|
||||||
|
<string name="_Permission_denied_Z7wlWK">"Permission denied"</string>
|
||||||
|
<string name="_Import_successful_2bLM3e">"Import successful"</string>
|
||||||
|
<string name="_Verifying____cS102">"Verifying..."</string>
|
||||||
|
<string name="_long_time_ago_1nwlFA">"long time ago"</string>
|
||||||
|
<string name="_months_ago_Z1TsskA">"months ago"</string>
|
||||||
|
<string name="_weeks_ago_Z2sT1GA">"weeks ago"</string>
|
||||||
|
<string name="_days_ago_2iCYkm">"days ago"</string>
|
||||||
|
<string name="yesterday">"yesterday"</string>
|
||||||
|
<string name="today">"today"</string>
|
||||||
|
<string name="_You_tried_this_recipe__ZUJOl3">"You tried this recipe:"</string>
|
||||||
|
<string name="snacks">"snacks"</string>
|
||||||
|
<string name="dinner">"dinner"</string>
|
||||||
|
<string name="lunch">"lunch"</string>
|
||||||
|
<string name="breakfast">"breakfast"</string>
|
||||||
|
<string name="_Crop_photo_1VL04J">"Crop photo"</string>
|
||||||
|
<string name="_REPLACE_PHOTO_ZLHhwH">"REPLACE PHOTO"</string>
|
||||||
|
<string name="_Recipe_photo_eqm9B">"Recipe photo"</string>
|
||||||
|
<string name="_EnRecipes_requires_storage_permission_in_order_to_set_recipe_photo__23OnNT">"EnRecipes requires storage permission in order to set recipe photo."</string>
|
||||||
|
<string name="Required">"Required"</string>
|
||||||
|
<string name="_New_category_Weg73">"New category"</string>
|
||||||
|
<string name="_New_yield_unit_1Oevd2">"New yield unit"</string>
|
||||||
|
<string name="_Remove_note__2wyMVE">"Remove note?"</string>
|
||||||
|
<string name="_Remove_combination__1dr2LS">"Remove combination?"</string>
|
||||||
|
<string name="_Remove_instruction__vkJfi">"Remove instruction?"</string>
|
||||||
|
<string name="_Remove_ingredient__2puvMO">"Remove ingredient?"</string>
|
||||||
|
<string name="_KEEP_EDITING_1o9uy3">"KEEP EDITING"</string>
|
||||||
|
<string name="DISCARD">"DISCARD"</string>
|
||||||
|
<string name="_Are_you_sure_you_want_to_discard_unsaved_changes_to_this_recipe__Z1G7sVC">"Are you sure you want to discard unsaved changes to this recipe?"</string>
|
||||||
|
<string name="_Unsaved_changes_9fqb4">"Unsaved changes"</string>
|
||||||
|
<string name="_Rename_category_Z1WzCco">"Rename category"</string>
|
||||||
|
<string name="Search">"Search"</string>
|
||||||
|
<string name="_Are_you_sure_you_want_to_delete_the_recipe_29DH9w">"Are you sure you want to delete the recipe"</string>
|
||||||
|
<string name="DELETE">"DELETE"</string>
|
||||||
|
<string name="_Delete_recipe__Z2tMYtE">"Delete recipe?"</string>
|
||||||
|
<string name="_Removed_from_Try_Later_1h5Bkp">"Removed from Try Later"</string>
|
||||||
|
<string name="_Added_to_Try_Later_Z1gaF37">"Added to Try Later"</string>
|
||||||
|
<string name="_Removed_from_Favourites_Z5k7LR">"Removed from Favourites"</string>
|
||||||
|
<string name="_Added_to_Favourites_2mzllO">"Added to Favourites"</string>
|
||||||
|
<string name="_Add_at_least_one_recipe_to_perform_a_backup_17xYaH">"Add at least one recipe to perform a backup"</string>
|
||||||
|
<string name="_EnRecipes_requires_storage_permission_in_order_to_backup_your_data_to_this_device__2cbvIq">"EnRecipes requires storage permission in order to backup your data to this device."</string>
|
||||||
|
<string name="CONTINUE">"CONTINUE"</string>
|
||||||
|
<string name="_NOT_NOW_Z1HD7qX">"NOT NOW"</string>
|
||||||
|
<string name="_EnRecipes_requires_storage_permission_in_order_to_import_your_data_from_a_previous_backup__1CKjb7">"EnRecipes requires storage permission in order to import your data from a previous backup."</string>
|
||||||
|
<string name="_Grant_permission_Z1UQBuh">"Grant permission"</string>
|
||||||
|
<string name="_EnRecipes_needs_to_be_restarted_for_the_app_language_to_take_effect__ZWGUtY">"EnRecipes needs to be restarted for the app language to take effect."</string>
|
||||||
|
<string name="_EnRecipes_needs_to_be_restarted_for_the_theme_change_to_take_effect__2kU319">"EnRecipes needs to be restarted for the theme change to take effect."</string>
|
||||||
|
<string name="RESTART">"RESTART"</string>
|
||||||
|
<string name="_Restart_required_Z22YINL">"Restart required"</string>
|
||||||
|
<string name="SET">"SET"</string>
|
||||||
|
<string name="_ADD_NEW_Zv8FjM">"ADD NEW"</string>
|
||||||
|
<string name="Share">"Share"</string>
|
||||||
|
<string name="Overview">"Overview"</string>
|
||||||
|
<string name="Recipe">"Recipe"</string>
|
||||||
|
<string name="Photo">"Photo"</string>
|
||||||
|
<string name="min">"min"</string>
|
||||||
|
<string name="hr">"hr"</string>
|
||||||
|
<string name="_My_Healthy_Recipe_Z1EqB8f">"My Healthy Recipe"</string>
|
||||||
|
<string name="_Nothing_here__Add_some_recipes_and_try_again__Z25A7Q">"Nothing here! Add some recipes and try again."</string>
|
||||||
|
<string name="_Select_a_recipe_2lL8x2">"Select a recipe"</string>
|
||||||
|
<string name="ADD">"ADD"</string>
|
||||||
|
<string name="REMOVE">"REMOVE"</string>
|
||||||
|
<string name="CANCEL">"CANCEL"</string>
|
||||||
|
<string name="_Last_modified_Z1yBAS3">"Last modified"</string>
|
||||||
|
<string name="Duration">"Duration"</string>
|
||||||
|
<string name="_Natural_order_Z1O8On5">"Natural order"</string>
|
||||||
|
<string name="_Sort_by_Zq01TF">"Sort by"</string>
|
||||||
|
<string name="Step">"Step"</string>
|
||||||
|
<string name="Item">"Item"</string>
|
||||||
|
<string name="_ADD_NOTE_ZyNw1r">"ADD NOTE"</string>
|
||||||
|
<string name="Notes">"Notes"</string>
|
||||||
|
<string name="Note">"Note"</string>
|
||||||
|
<string name="_ADD_COMBINATION_2q9HWq">"ADD COMBINATION"</string>
|
||||||
|
<string name="Combinations">"Combinations"</string>
|
||||||
|
<string name="_ADD_STEP_ZyMPOe">"ADD STEP"</string>
|
||||||
|
<string name="Instructions">"Instructions"</string>
|
||||||
|
<string name="Instruction">"Instruction"</string>
|
||||||
|
<string name="_ADD_INGREDIENT_29sSLU">"ADD INGREDIENT"</string>
|
||||||
|
<string name="Ingredients">"Ingredients"</string>
|
||||||
|
<string name="Ingredient">"Ingredient"</string>
|
||||||
|
<string name="_Yield_measured_in_2OoRT">"Yield measured in"</string>
|
||||||
|
<string name="_Yield_quantity_ZHx3jw">"Yield quantity"</string>
|
||||||
|
<string name="_Cooking_time_2w2fEw">"Cooking time"</string>
|
||||||
|
<string name="_Preparation_time_15BfxT">"Preparation time"</string>
|
||||||
|
<string name="Category">"Category"</string>
|
||||||
|
<string name="Title">"Title"</string>
|
||||||
|
<string name="_Edit_recipe_ZPvwDP">"Edit recipe"</string>
|
||||||
|
<string name="_New_recipe_Z1Y2YKJ">"New recipe"</string>
|
||||||
|
<string name="_Follow_on_Mastodon_Z1v6e4V">"Follow on Mastodon"</string>
|
||||||
|
<string name="_Follow_on_GitHub_Z1GjptH">"Follow on GitHub"</string>
|
||||||
|
<string name="_Vishnu_Raghav_B_1qnRnC">"Vishnu Raghav B"</string>
|
||||||
|
<string name="Author">"Author"</string>
|
||||||
|
<string name="_for_reporting_issues__suggestions_and_feedback_Z1JUmyE">"for reporting issues, suggestions and feedback"</string>
|
||||||
|
<string name="_Join_the_Telegram_group_ZAXQgc">"Join the Telegram group"</string>
|
||||||
|
<string name="_View_project_on_GitHub_1hrJ0U">"View project on GitHub"</string>
|
||||||
|
<string name="Version">"Version"</string>
|
||||||
|
<string name="_Supports_full_backups_exported_by_this_app_ZYs4f2">"Supports full backups exported by this app"</string>
|
||||||
|
<string name="_Import_from_backup_Z28HsC0">"Import from backup"</string>
|
||||||
|
<string name="_Generates_a_zip_file_that_contains_all_your_data__This_file_can_be_imported_back__Z19m3xY">"Generates a zip file that contains all your data. This file can be imported back."</string>
|
||||||
|
<string name="_Export_a_full_backup_TJfra">"Export a full backup"</string>
|
||||||
|
<string name="Database">"Database"</string>
|
||||||
|
<string name="Dark">"Dark"</string>
|
||||||
|
<string name="Light">"Light"</string>
|
||||||
|
<string name="Theme">"Theme"</string>
|
||||||
|
<string name="_System_default_Z1jruVS">"System default"</string>
|
||||||
|
<string name="_App_language_DzFsk">"App language"</string>
|
||||||
|
<string name="Interface">"Interface"</string>
|
||||||
|
<string name="_Your_search_did_not_match_any_recipes_in_your_try_later_list_Z2wWbA1">"Your search did not match any recipes in your try later list"</string>
|
||||||
|
<string name="_Your_search_did_not_match_any_recipes_in_your_favourites_1ylvHN">"Your search did not match any recipes in your favourites"</string>
|
||||||
|
<string name="_Your_search_did_not_match_any_recipes_in_this_category_P7J4V">"Your search did not match any recipes in this category"</string>
|
||||||
|
<string name="_Your_search_did_not_match_any_recipes_Z1eppHH">"Your search did not match any recipes"</string>
|
||||||
|
<string name="_No_recipes_found_Z125IxD">"No recipes found"</string>
|
||||||
|
<string name="_Category_looks_empty_ZAK5qU">"Category looks empty"</string>
|
||||||
|
<string name="_Recipes_you_mark_as_favourite_will_be_listed_here_Z1iIHgY">"Recipes you mark as favourite will be listed here"</string>
|
||||||
|
<string name="_No_favourites_yet_aPSoG">"No favourites yet"</string>
|
||||||
|
<string name="_Recipes_you_mark_as_try_later_will_be_listed_here_Z1ITwPV">"Recipes you mark as try later will be listed here"</string>
|
||||||
|
<string name="_All_done__72KYl">"All done!"</string>
|
||||||
|
<string name="_Use_the_pencil_button_to_add_some_notes_Z1wyyeb">"Use the pencil button to add some notes"</string>
|
||||||
|
<string name="_Use_the_pencil_button_to_add_some_combinations_6NhFS">"Use the pencil button to add some combinations"</string>
|
||||||
|
<string name="_Use_the_pencil_button_to_add_some_instructions_ZAi0PH">"Use the pencil button to add some instructions"</string>
|
||||||
|
<string name="_Use_the_pencil_button_to_add_some_ingredients_Z1xOX8S">"Use the pencil button to add some ingredients"</string>
|
||||||
|
<string name="_Use_the_plus_button_to_add_one_1h20ms">"Use the plus button to add one"</string>
|
||||||
|
<string name="_Start_adding_your_recipes__rwnVV">"Start adding your recipes!"</string>
|
||||||
|
<string name="large">"large"</string>
|
||||||
|
<string name="medium">"medium"</string>
|
||||||
|
<string name="small">"small"</string>
|
||||||
|
<string name="stick">"stick"</string>
|
||||||
|
<string name="dozen">"dozen"</string>
|
||||||
|
<string name="drop">"drop"</string>
|
||||||
|
<string name="pinch">"pinch"</string>
|
||||||
|
<string name="piece">"piece"</string>
|
||||||
|
<string name="clove">"clove"</string>
|
||||||
|
<string name="leaf">"leaf"</string>
|
||||||
|
<string name="in">"in"</string>
|
||||||
|
<string name="cm">"cm"</string>
|
||||||
|
<string name="kg">"kg"</string>
|
||||||
|
<string name="g">"g"</string>
|
||||||
|
<string name="mg">"mg"</string>
|
||||||
|
<string name="lb">"lb"</string>
|
||||||
|
<string name="oz">"oz"</string>
|
||||||
|
<string name="l">"l"</string>
|
||||||
|
<string name="ml">"ml"</string>
|
||||||
|
<string name="gal">"gal"</string>
|
||||||
|
<string name="qt">"qt"</string>
|
||||||
|
<string name="pt">"pt"</string>
|
||||||
|
<string name="cup">"cup"</string>
|
||||||
|
<string name="_fl_oz_72kqu">"fl oz"</string>
|
||||||
|
<string name="tbsp">"tbsp"</string>
|
||||||
|
<string name="dsp">"dsp"</string>
|
||||||
|
<string name="tsp">"tsp"</string>
|
||||||
|
<string name="Unit">"Unit"</string>
|
||||||
|
<string name="unit">"unit"</string>
|
||||||
|
<string name="Loaf">"Loaf"</string>
|
||||||
|
<string name="Patty">"Patty"</string>
|
||||||
|
<string name="Roll">"Roll"</string>
|
||||||
|
<string name="Litre">"Litre"</string>
|
||||||
|
<string name="Millilitre">"Millilitre"</string>
|
||||||
|
<string name="Gallon">"Gallon"</string>
|
||||||
|
<string name="Cup">"Cup"</string>
|
||||||
|
<string name="Kilogram">"Kilogram"</string>
|
||||||
|
<string name="Gram">"Gram"</string>
|
||||||
|
<string name="Pound">"Pound"</string>
|
||||||
|
<string name="Ounce">"Ounce"</string>
|
||||||
|
<string name="_Fluid_Ounce_bd10L">"Fluid Ounce"</string>
|
||||||
|
<string name="Tablespoon">"Tablespoon"</string>
|
||||||
|
<string name="Teaspoon">"Teaspoon"</string>
|
||||||
|
<string name="Piece">"Piece"</string>
|
||||||
|
<string name="Serving">"Serving"</string>
|
||||||
|
<string name="Vegetarian">"Vegetarian"</string>
|
||||||
|
<string name="Vegan">"Vegan"</string>
|
||||||
|
<string name="Undefined">"Undefined"</string>
|
||||||
|
<string name="Soups">"Soups"</string>
|
||||||
|
<string name="Snacks">"Snacks"</string>
|
||||||
|
<string name="_Side_dishes_Z1Et4Vg">"Side dishes"</string>
|
||||||
|
<string name="Seafood">"Seafood"</string>
|
||||||
|
<string name="Sauces">"Sauces"</string>
|
||||||
|
<string name="Salads">"Salads"</string>
|
||||||
|
<string name="Rice">"Rice"</string>
|
||||||
|
<string name="Poultry">"Poultry"</string>
|
||||||
|
<string name="Pasta">"Pasta"</string>
|
||||||
|
<string name="Noodles">"Noodles"</string>
|
||||||
|
<string name="Meat">"Meat"</string>
|
||||||
|
<string name="_Main_dishes_u6RGQ">"Main dishes"</string>
|
||||||
|
<string name="Lunch">"Lunch"</string>
|
||||||
|
<string name="Healthy">"Healthy"</string>
|
||||||
|
<string name="Drinks">"Drinks"</string>
|
||||||
|
<string name="Dinner">"Dinner"</string>
|
||||||
|
<string name="Desserts">"Desserts"</string>
|
||||||
|
<string name="Breakfast">"Breakfast"</string>
|
||||||
|
<string name="Breads">"Breads"</string>
|
||||||
|
<string name="Beverages">"Beverages"</string>
|
||||||
|
<string name="Barbecue">"Barbecue"</string>
|
||||||
|
<string name="Appetizers">"Appetizers"</string>
|
||||||
|
<string name="About">"About"</string>
|
||||||
|
<string name="Settings">"Settings"</string>
|
||||||
|
<string name="RENAME">"RENAME"</string>
|
||||||
|
<string name="DONE">"DONE"</string>
|
||||||
|
<string name="Categories">"Categories"</string>
|
||||||
|
<string name="_Meal_Planner_2aq4oj">"Meal Planner"</string>
|
||||||
|
<string name="Favourites">"Favourites"</string>
|
||||||
|
<string name="_Try_Later_If7PG">"Try Later"</string>
|
||||||
|
<string name="EnRecipes">"EnRecipes"</string>
|
||||||
|
<string name="_app_name_1k3Sbz">"EnRecipes"</string>
|
||||||
|
<string name="app_name">"EnRecipes"</string>
|
||||||
|
<string name="title_activity_kimera">"EnRecipes"</string>
|
||||||
|
</resources>
|
195
app/store.js
|
@ -1,7 +1,11 @@
|
||||||
import Vue from "vue"
|
import Vue from "vue"
|
||||||
import Vuex from "vuex"
|
import Vuex from "vuex"
|
||||||
import { Couchbase } from "nativescript-couchbase-plugin"
|
import {
|
||||||
import { getFileAccess } from "@nativescript/core"
|
Couchbase
|
||||||
|
} from "nativescript-couchbase-plugin"
|
||||||
|
import {
|
||||||
|
getFileAccess
|
||||||
|
} from "@nativescript/core"
|
||||||
const EnRecipesDB = new Couchbase("EnRecipes")
|
const EnRecipesDB = new Couchbase("EnRecipes")
|
||||||
const userCategoriesDB = new Couchbase("userCategories")
|
const userCategoriesDB = new Couchbase("userCategories")
|
||||||
const userYieldUnitsDB = new Couchbase("userYieldUnits")
|
const userYieldUnitsDB = new Couchbase("userYieldUnits")
|
||||||
|
@ -11,7 +15,7 @@ Vue.use(Vuex)
|
||||||
|
|
||||||
const defaultCategories = [
|
const defaultCategories = [
|
||||||
"Appetizers",
|
"Appetizers",
|
||||||
"BBQ",
|
"Barbecue",
|
||||||
"Beverages",
|
"Beverages",
|
||||||
"Breads",
|
"Breads",
|
||||||
"Breakfast",
|
"Breakfast",
|
||||||
|
@ -81,6 +85,7 @@ export default new Vuex.Store({
|
||||||
"in",
|
"in",
|
||||||
"leaf",
|
"leaf",
|
||||||
"clove",
|
"clove",
|
||||||
|
"piece",
|
||||||
"pinch",
|
"pinch",
|
||||||
"drop",
|
"drop",
|
||||||
"dozen",
|
"dozen",
|
||||||
|
@ -135,17 +140,29 @@ export default new Vuex.Store({
|
||||||
outline: "\ueb07",
|
outline: "\ueb07",
|
||||||
calendar: "\uec55",
|
calendar: "\uec55",
|
||||||
today: "\ue97c",
|
today: "\ue97c",
|
||||||
|
globe: "\uea5a",
|
||||||
},
|
},
|
||||||
currentComponent: "EnRecipes",
|
currentComponent: "EnRecipes",
|
||||||
|
language: [{
|
||||||
|
locale: 'en',
|
||||||
|
title: 'English'
|
||||||
|
}, {
|
||||||
|
locale: 'ta',
|
||||||
|
title: 'தமிழ்'
|
||||||
|
}, ]
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
initializeRecipes(state) {
|
initializeRecipes(state) {
|
||||||
EnRecipesDB.query({ select: [] }).forEach((recipe) => {
|
EnRecipesDB.query({
|
||||||
|
select: []
|
||||||
|
}).forEach((recipe) => {
|
||||||
state.recipes.push(recipe)
|
state.recipes.push(recipe)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
initializeCategories(state) {
|
initializeCategories(state) {
|
||||||
let isCategoriesStored = userCategoriesDB.query({ select: [] }).length
|
let isCategoriesStored = userCategoriesDB.query({
|
||||||
|
select: []
|
||||||
|
}).length
|
||||||
if (isCategoriesStored) {
|
if (isCategoriesStored) {
|
||||||
state.userCategories = userCategoriesDB.getDocument(
|
state.userCategories = userCategoriesDB.getDocument(
|
||||||
"userCategories"
|
"userCategories"
|
||||||
|
@ -155,8 +172,9 @@ export default new Vuex.Store({
|
||||||
categoriesWithRecipes.includes(e)
|
categoriesWithRecipes.includes(e)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
userCategoriesDB.createDocument(
|
userCategoriesDB.createDocument({
|
||||||
{ userCategories: [] },
|
userCategories: []
|
||||||
|
},
|
||||||
"userCategories"
|
"userCategories"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -164,7 +182,9 @@ export default new Vuex.Store({
|
||||||
state.categories.sort()
|
state.categories.sort()
|
||||||
},
|
},
|
||||||
initializeYieldUnits(state) {
|
initializeYieldUnits(state) {
|
||||||
let isYieldUnitsStored = userYieldUnitsDB.query({ select: [] }).length
|
let isYieldUnitsStored = userYieldUnitsDB.query({
|
||||||
|
select: []
|
||||||
|
}).length
|
||||||
if (isYieldUnitsStored) {
|
if (isYieldUnitsStored) {
|
||||||
state.userYieldUnits = userYieldUnitsDB.getDocument(
|
state.userYieldUnits = userYieldUnitsDB.getDocument(
|
||||||
"userYieldUnits"
|
"userYieldUnits"
|
||||||
|
@ -174,19 +194,24 @@ export default new Vuex.Store({
|
||||||
yieldUnitsWithRecipes.includes(e)
|
yieldUnitsWithRecipes.includes(e)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
userYieldUnitsDB.createDocument(
|
userYieldUnitsDB.createDocument({
|
||||||
{ userYieldUnits: [] },
|
userYieldUnits: []
|
||||||
|
},
|
||||||
"userYieldUnits"
|
"userYieldUnits"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
state.yieldUnits = [...defaultYieldUnits, ...state.userYieldUnits]
|
state.yieldUnits = [...defaultYieldUnits, ...state.userYieldUnits]
|
||||||
},
|
},
|
||||||
initializeMealPlans(state) {
|
initializeMealPlans(state) {
|
||||||
let isMealPlansDBStored = mealPlansDB.query({ select: [] }).length
|
let isMealPlansDBStored = mealPlansDB.query({
|
||||||
|
select: []
|
||||||
|
}).length
|
||||||
if (isMealPlansDBStored) {
|
if (isMealPlansDBStored) {
|
||||||
state.mealPlans = mealPlansDB.getDocument("mealPlans").mealPlans
|
state.mealPlans = mealPlansDB.getDocument("mealPlans").mealPlans
|
||||||
} else {
|
} else {
|
||||||
mealPlansDB.createDocument({ mealPlans: [] }, "mealPlans")
|
mealPlansDB.createDocument({
|
||||||
|
mealPlans: []
|
||||||
|
}, "mealPlans")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -196,18 +221,23 @@ export default new Vuex.Store({
|
||||||
localRecipesIDs = state.recipes.map((e) => e.id)
|
localRecipesIDs = state.recipes.map((e) => e.id)
|
||||||
partition = recipes.reduce(
|
partition = recipes.reduce(
|
||||||
(result, recipe, i) => {
|
(result, recipe, i) => {
|
||||||
localRecipesIDs.indexOf(recipe.id) < 0
|
localRecipesIDs.indexOf(recipe.id) < 0 ?
|
||||||
? result[0].push(recipe) // create candidates
|
result[0].push(recipe) // create candidates
|
||||||
: result[1].push(recipe) // update candidates
|
:
|
||||||
|
result[1].push(recipe) // update candidates
|
||||||
return result
|
return result
|
||||||
},
|
},
|
||||||
[[], []]
|
[
|
||||||
|
[],
|
||||||
|
[]
|
||||||
|
]
|
||||||
)
|
)
|
||||||
if (partition[0].length) createDocuments(partition[0])
|
if (partition[0].length) createDocuments(partition[0])
|
||||||
if (partition[1].length) updateDocuments(partition[1])
|
if (partition[1].length) updateDocuments(partition[1])
|
||||||
} else {
|
} else {
|
||||||
createDocuments(recipes)
|
createDocuments(recipes)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUpdatedData(data) {
|
function getUpdatedData(data) {
|
||||||
return data.map((recipe) => {
|
return data.map((recipe) => {
|
||||||
let r = Object.assign({}, recipe)
|
let r = Object.assign({}, recipe)
|
||||||
|
@ -219,6 +249,7 @@ export default new Vuex.Store({
|
||||||
return r
|
return r
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function createDocuments(data) {
|
function createDocuments(data) {
|
||||||
data = getUpdatedData(data)
|
data = getUpdatedData(data)
|
||||||
state.recipes = [...state.recipes, ...data]
|
state.recipes = [...state.recipes, ...data]
|
||||||
|
@ -226,6 +257,7 @@ export default new Vuex.Store({
|
||||||
EnRecipesDB.createDocument(recipe, recipe.id)
|
EnRecipesDB.createDocument(recipe, recipe.id)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateDocuments(data) {
|
function updateDocuments(data) {
|
||||||
data = getUpdatedData(data)
|
data = getUpdatedData(data)
|
||||||
data.forEach((recipe) => {
|
data.forEach((recipe) => {
|
||||||
|
@ -271,7 +303,10 @@ export default new Vuex.Store({
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
addRecipe(state, { id, recipe }) {
|
addRecipe(state, {
|
||||||
|
id,
|
||||||
|
recipe
|
||||||
|
}) {
|
||||||
state.recipes.push(recipe)
|
state.recipes.push(recipe)
|
||||||
EnRecipesDB.createDocument(recipe, id)
|
EnRecipesDB.createDocument(recipe, id)
|
||||||
},
|
},
|
||||||
|
@ -296,7 +331,10 @@ export default new Vuex.Store({
|
||||||
state.yieldUnits = [...defaultYieldUnits, ...state.userYieldUnits]
|
state.yieldUnits = [...defaultYieldUnits, ...state.userYieldUnits]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
addMealPlan(state, { event, eventColor }) {
|
addMealPlan(state, {
|
||||||
|
event,
|
||||||
|
eventColor
|
||||||
|
}) {
|
||||||
state.mealPlans.push({
|
state.mealPlans.push({
|
||||||
title: event.title,
|
title: event.title,
|
||||||
startDate: event.startDate,
|
startDate: event.startDate,
|
||||||
|
@ -308,7 +346,10 @@ export default new Vuex.Store({
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
deleteRecipe(state, { index, id }) {
|
deleteRecipe(state, {
|
||||||
|
index,
|
||||||
|
id
|
||||||
|
}) {
|
||||||
getFileAccess().deleteFile(state.recipes[index].imageSrc)
|
getFileAccess().deleteFile(state.recipes[index].imageSrc)
|
||||||
state.recipes.splice(index, 1)
|
state.recipes.splice(index, 1)
|
||||||
EnRecipesDB.deleteDocument(id)
|
EnRecipesDB.deleteDocument(id)
|
||||||
|
@ -319,7 +360,10 @@ export default new Vuex.Store({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
deleteMealPlan(state, { title, startDate }) {
|
deleteMealPlan(state, {
|
||||||
|
title,
|
||||||
|
startDate
|
||||||
|
}) {
|
||||||
let mealPlan = state.mealPlans.filter((e) => {
|
let mealPlan = state.mealPlans.filter((e) => {
|
||||||
console.log(e.startDate, startDate)
|
console.log(e.startDate, startDate)
|
||||||
let sd = new Date(e.startDate).getTime()
|
let sd = new Date(e.startDate).getTime()
|
||||||
|
@ -335,14 +379,22 @@ export default new Vuex.Store({
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
overwriteRecipe(state, { id, recipe }) {
|
overwriteRecipe(state, {
|
||||||
|
id,
|
||||||
|
recipe
|
||||||
|
}) {
|
||||||
let index = state.recipes.indexOf(
|
let index = state.recipes.indexOf(
|
||||||
state.recipes.filter((e) => e.id === id)[0]
|
state.recipes.filter((e) => e.id === id)[0]
|
||||||
)
|
)
|
||||||
Object.assign(state.recipes[index], recipe)
|
Object.assign(state.recipes[index], recipe)
|
||||||
EnRecipesDB.updateDocument(id, recipe)
|
EnRecipesDB.updateDocument(id, recipe)
|
||||||
},
|
},
|
||||||
toggleState(state, { id, recipe, key, setDate }) {
|
toggleState(state, {
|
||||||
|
id,
|
||||||
|
recipe,
|
||||||
|
key,
|
||||||
|
setDate
|
||||||
|
}) {
|
||||||
let index = state.recipes.indexOf(
|
let index = state.recipes.indexOf(
|
||||||
state.recipes.filter((e) => e.id === id)[0]
|
state.recipes.filter((e) => e.id === id)[0]
|
||||||
)
|
)
|
||||||
|
@ -350,7 +402,10 @@ export default new Vuex.Store({
|
||||||
if (setDate) state.recipes[index].lastTried = new Date()
|
if (setDate) state.recipes[index].lastTried = new Date()
|
||||||
EnRecipesDB.updateDocument(id, recipe)
|
EnRecipesDB.updateDocument(id, recipe)
|
||||||
},
|
},
|
||||||
setRecipeAsTried(state, { id, recipe }) {
|
setRecipeAsTried(state, {
|
||||||
|
id,
|
||||||
|
recipe
|
||||||
|
}) {
|
||||||
let index = state.recipes.indexOf(
|
let index = state.recipes.indexOf(
|
||||||
state.recipes.filter((e) => e.id === id)[0]
|
state.recipes.filter((e) => e.id === id)[0]
|
||||||
)
|
)
|
||||||
|
@ -362,7 +417,10 @@ export default new Vuex.Store({
|
||||||
state.recipes[index].lastTried = new Date()
|
state.recipes[index].lastTried = new Date()
|
||||||
EnRecipesDB.updateDocument(state.recipes[index].id, state.recipes[index])
|
EnRecipesDB.updateDocument(state.recipes[index].id, state.recipes[index])
|
||||||
},
|
},
|
||||||
renameCategory(state, { current, updated }) {
|
renameCategory(state, {
|
||||||
|
current,
|
||||||
|
updated
|
||||||
|
}) {
|
||||||
let lowercase = state.categories.map((e) => e.toLowerCase())
|
let lowercase = state.categories.map((e) => e.toLowerCase())
|
||||||
if (lowercase.indexOf(updated.toLowerCase()) == -1) {
|
if (lowercase.indexOf(updated.toLowerCase()) == -1) {
|
||||||
state.userCategories.push(updated)
|
state.userCategories.push(updated)
|
||||||
|
@ -384,7 +442,10 @@ export default new Vuex.Store({
|
||||||
setCurrentComponent(state, comp) {
|
setCurrentComponent(state, comp) {
|
||||||
state.currentComponent = comp
|
state.currentComponent = comp
|
||||||
},
|
},
|
||||||
unSyncCombinations(state, { id, combinations }) {
|
unSyncCombinations(state, {
|
||||||
|
id,
|
||||||
|
combinations
|
||||||
|
}) {
|
||||||
state.recipes.forEach((e, i) => {
|
state.recipes.forEach((e, i) => {
|
||||||
if (combinations.includes(e.id)) {
|
if (combinations.includes(e.id)) {
|
||||||
state.recipes[i].combinations.splice(e.combinations.indexOf(id), 1)
|
state.recipes[i].combinations.splice(e.combinations.indexOf(id), 1)
|
||||||
|
@ -394,71 +455,113 @@ export default new Vuex.Store({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
initializeRecipes({ commit }) {
|
initializeRecipes({
|
||||||
|
commit
|
||||||
|
}) {
|
||||||
commit("initializeRecipes")
|
commit("initializeRecipes")
|
||||||
},
|
},
|
||||||
initializeCategories({ commit }) {
|
initializeCategories({
|
||||||
|
commit
|
||||||
|
}) {
|
||||||
commit("initializeCategories")
|
commit("initializeCategories")
|
||||||
},
|
},
|
||||||
initializeYieldUnits({ commit }) {
|
initializeYieldUnits({
|
||||||
|
commit
|
||||||
|
}) {
|
||||||
commit("initializeYieldUnits")
|
commit("initializeYieldUnits")
|
||||||
},
|
},
|
||||||
initializeMealPlans({ commit }) {
|
initializeMealPlans({
|
||||||
|
commit
|
||||||
|
}) {
|
||||||
commit("initializeMealPlans")
|
commit("initializeMealPlans")
|
||||||
},
|
},
|
||||||
|
|
||||||
importRecipesAction({ commit }, recipes) {
|
importRecipesAction({
|
||||||
|
commit
|
||||||
|
}, recipes) {
|
||||||
commit("importRecipes", recipes)
|
commit("importRecipes", recipes)
|
||||||
},
|
},
|
||||||
importCategoriesAction({ commit }, categories) {
|
importCategoriesAction({
|
||||||
|
commit
|
||||||
|
}, categories) {
|
||||||
commit("importCategories", categories)
|
commit("importCategories", categories)
|
||||||
},
|
},
|
||||||
importYieldUnitsAction({ commit }, yieldUnits) {
|
importYieldUnitsAction({
|
||||||
|
commit
|
||||||
|
}, yieldUnits) {
|
||||||
commit("importYieldUnits", yieldUnits)
|
commit("importYieldUnits", yieldUnits)
|
||||||
},
|
},
|
||||||
importMealPlansAction({ commit }, mealPlans) {
|
importMealPlansAction({
|
||||||
|
commit
|
||||||
|
}, mealPlans) {
|
||||||
commit("importMealPlans", mealPlans)
|
commit("importMealPlans", mealPlans)
|
||||||
},
|
},
|
||||||
|
|
||||||
addRecipeAction({ commit }, recipe) {
|
addRecipeAction({
|
||||||
|
commit
|
||||||
|
}, recipe) {
|
||||||
commit("addRecipe", recipe)
|
commit("addRecipe", recipe)
|
||||||
},
|
},
|
||||||
addYieldUnitAction({ commit }, yieldUnit) {
|
addYieldUnitAction({
|
||||||
|
commit
|
||||||
|
}, yieldUnit) {
|
||||||
commit("addYieldUnit", yieldUnit)
|
commit("addYieldUnit", yieldUnit)
|
||||||
},
|
},
|
||||||
addCategoryAction({ commit }, category) {
|
addCategoryAction({
|
||||||
|
commit
|
||||||
|
}, category) {
|
||||||
commit("addCategory", category)
|
commit("addCategory", category)
|
||||||
},
|
},
|
||||||
addMealPlanAction({ commit }, mealPlan) {
|
addMealPlanAction({
|
||||||
|
commit
|
||||||
|
}, mealPlan) {
|
||||||
commit("addMealPlan", mealPlan)
|
commit("addMealPlan", mealPlan)
|
||||||
},
|
},
|
||||||
|
|
||||||
deleteMealPlanAction({ commit }, mealPlan) {
|
deleteMealPlanAction({
|
||||||
|
commit
|
||||||
|
}, mealPlan) {
|
||||||
commit("deleteMealPlan", mealPlan)
|
commit("deleteMealPlan", mealPlan)
|
||||||
},
|
},
|
||||||
deleteRecipeAction({ commit }, recipe) {
|
deleteRecipeAction({
|
||||||
|
commit
|
||||||
|
}, recipe) {
|
||||||
commit("deleteRecipe", recipe)
|
commit("deleteRecipe", recipe)
|
||||||
},
|
},
|
||||||
|
|
||||||
overwriteRecipeAction({ commit }, updatedRecipe) {
|
overwriteRecipeAction({
|
||||||
|
commit
|
||||||
|
}, updatedRecipe) {
|
||||||
commit("overwriteRecipe", updatedRecipe)
|
commit("overwriteRecipe", updatedRecipe)
|
||||||
},
|
},
|
||||||
toggleStateAction({ commit }, toggledRecipe) {
|
toggleStateAction({
|
||||||
|
commit
|
||||||
|
}, toggledRecipe) {
|
||||||
commit("toggleState", toggledRecipe)
|
commit("toggleState", toggledRecipe)
|
||||||
},
|
},
|
||||||
setRecipeAsTriedAction({ commit }, recipe) {
|
setRecipeAsTriedAction({
|
||||||
|
commit
|
||||||
|
}, recipe) {
|
||||||
commit("setRecipeAsTried", recipe)
|
commit("setRecipeAsTried", recipe)
|
||||||
},
|
},
|
||||||
setLastTriedDateAction({ commit }, index) {
|
setLastTriedDateAction({
|
||||||
|
commit
|
||||||
|
}, index) {
|
||||||
commit("setLastTriedDate", index)
|
commit("setLastTriedDate", index)
|
||||||
},
|
},
|
||||||
renameCategoryAction({ commit }, category) {
|
renameCategoryAction({
|
||||||
|
commit
|
||||||
|
}, category) {
|
||||||
commit("renameCategory", category)
|
commit("renameCategory", category)
|
||||||
},
|
},
|
||||||
setCurrentComponentAction({ commit }, comp) {
|
setCurrentComponentAction({
|
||||||
|
commit
|
||||||
|
}, comp) {
|
||||||
commit("setCurrentComponent", comp)
|
commit("setCurrentComponent", comp)
|
||||||
},
|
},
|
||||||
unSyncCombinationsAction({ commit }, combinations) {
|
unSyncCombinationsAction({
|
||||||
|
commit
|
||||||
|
}, combinations) {
|
||||||
commit("unSyncCombinations", combinations)
|
commit("unSyncCombinations", combinations)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
5
fastlane/metadata/android/en-US/changelogs/3.txt
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
- Fixed several bugs causing app crashes
|
||||||
|
- Minor UI improvements
|
||||||
|
- Application language support
|
||||||
|
- Added Tamil
|
||||||
|
- More languages coming soon!
|
|
@ -5,9 +5,9 @@ EnRecipes is an easy to use, privacy-friendly digital cookbook that lets you cre
|
||||||
▸ Add photo, notes and combinations to your recipes
|
▸ Add photo, notes and combinations to your recipes
|
||||||
▸ Organise your recipes by category
|
▸ Organise your recipes by category
|
||||||
▸ Quickly search for your recipes
|
▸ Quickly search for your recipes
|
||||||
▸ Mark recipes as favorites and add them to your Try Later list
|
▸ Mark recipes as favourites and add them to your Try Later list
|
||||||
▸ Scale your recipe ingredients to serve more or less people
|
▸ Scale your recipe ingredients to serve more or less people
|
||||||
▸ Get notified of the last time you tried a recipe
|
▸ Get notified of when you last tried a recipe
|
||||||
▸ Share your recipe to anyone by any means as a nicely formatted message. You can share the recipe photo too.
|
▸ Share your recipe to anyone by any means as a nicely formatted message. You can share the recipe photo too.
|
||||||
▸ Create meal plans
|
▸ Create meal plans
|
||||||
▸ Import/Export recipes
|
▸ Import/Export recipes
|
||||||
|
@ -16,7 +16,5 @@ EnRecipes is an easy to use, privacy-friendly digital cookbook that lets you cre
|
||||||
▸ No internet access is required and never asks for any unwanted permissions
|
▸ No internet access is required and never asks for any unwanted permissions
|
||||||
▸ 100% free and open-source
|
▸ 100% free and open-source
|
||||||
|
|
||||||
Lots of interesting features on the way...
|
|
||||||
|
|
||||||
<b>Credits</b>
|
<b>Credits</b>
|
||||||
This app was written in my free time using NativeScript. I would like to thank all those people who helped me understand the concepts during the process and my special thanks to the NativeScript team and the community.
|
This app was written in my free time using NativeScript. I would like to thank all those people who helped me understand the concepts during the process and my special thanks to the NativeScript team and the community.
|
||||||
|
|
1
hooks/before-checkForChanges/nativescript-localize.js
Normal file
|
@ -0,0 +1 @@
|
||||||
|
module.exports = require("@nativescript/localize/hooks/before-checkForChanges.js");
|
1
hooks/before-watchPatterns/nativescript-localize.js
Normal file
|
@ -0,0 +1 @@
|
||||||
|
module.exports = require("@nativescript/localize/hooks/before-watchPatterns.js");
|
|
@ -2,7 +2,7 @@ import { NativeScriptConfig } from "@nativescript/core"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
id: "com.vishnuraghav.enrecipes",
|
id: "com.vishnuraghav.enrecipes",
|
||||||
appResourcesPath: "app/App_Resources",
|
appResourcesPath: "app/resources",
|
||||||
android: {
|
android: {
|
||||||
v8Flags: "--expose_gc",
|
v8Flags: "--expose_gc",
|
||||||
markingMode: "none",
|
markingMode: "none",
|
||||||
|
|
80
package-lock.json
generated
|
@ -1131,6 +1131,17 @@
|
||||||
"mkdirp": "^1.0.4"
|
"mkdirp": "^1.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@nativescript/localize": {
|
||||||
|
"version": "5.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@nativescript/localize/-/localize-5.0.2.tgz",
|
||||||
|
"integrity": "sha512-TokwtXhb3oROr3ST0vCsuDHkTl+pi2caNEkTZNTlXXt5lBd4qyLpooo6ua0O7rVZ6VDcFD9rmJU0sPyNJCMvcw==",
|
||||||
|
"requires": {
|
||||||
|
"mkdirp": "^1.0.4",
|
||||||
|
"shorthash": "0.0.2",
|
||||||
|
"simple-plist": "^1.1.0",
|
||||||
|
"sprintf-js": "^1.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@nativescript/social-share": {
|
"@nativescript/social-share": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@nativescript/social-share/-/social-share-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@nativescript/social-share/-/social-share-2.0.1.tgz",
|
||||||
|
@ -2032,8 +2043,7 @@
|
||||||
"base64-js": {
|
"base64-js": {
|
||||||
"version": "1.5.1",
|
"version": "1.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||||
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"bcrypt-pbkdf": {
|
"bcrypt-pbkdf": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
|
@ -2056,6 +2066,11 @@
|
||||||
"tryer": "^1.0.1"
|
"tryer": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"big-integer": {
|
||||||
|
"version": "1.6.48",
|
||||||
|
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz",
|
||||||
|
"integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w=="
|
||||||
|
},
|
||||||
"big.js": {
|
"big.js": {
|
||||||
"version": "5.2.2",
|
"version": "5.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
|
||||||
|
@ -2135,6 +2150,22 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"bplist-creator": {
|
||||||
|
"version": "0.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.0.8.tgz",
|
||||||
|
"integrity": "sha512-Za9JKzD6fjLC16oX2wsXfc+qBEhJBJB1YPInoAQpMLhDuj5aVOv1baGeIQSq1Fr3OCqzvsoQcSBSwGId/Ja2PA==",
|
||||||
|
"requires": {
|
||||||
|
"stream-buffers": "~2.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"bplist-parser": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==",
|
||||||
|
"requires": {
|
||||||
|
"big-integer": "^1.6.44"
|
||||||
|
}
|
||||||
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
|
@ -6220,6 +6251,16 @@
|
||||||
"find-up": "^4.0.0"
|
"find-up": "^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"plist": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/plist/-/plist-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ==",
|
||||||
|
"requires": {
|
||||||
|
"base64-js": "^1.2.3",
|
||||||
|
"xmlbuilder": "^9.0.7",
|
||||||
|
"xmldom": "0.1.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"posix-character-classes": {
|
"posix-character-classes": {
|
||||||
"version": "0.1.1",
|
"version": "0.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
|
||||||
|
@ -7333,12 +7374,27 @@
|
||||||
"rechoir": "^0.6.2"
|
"rechoir": "^0.6.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"shorthash": {
|
||||||
|
"version": "0.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/shorthash/-/shorthash-0.0.2.tgz",
|
||||||
|
"integrity": "sha1-WbJo7sveWQOLMNogK8+93rLEpOs="
|
||||||
|
},
|
||||||
"signal-exit": {
|
"signal-exit": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
|
||||||
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
|
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"simple-plist": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-pKMCVKvZbZTsqYR6RKgLfBHkh2cV89GXcA/0CVPje3sOiNOnXA8+rp/ciAMZ7JRaUdLzlEM6JFfUn+fS6Nt3hg==",
|
||||||
|
"requires": {
|
||||||
|
"bplist-creator": "0.0.8",
|
||||||
|
"bplist-parser": "0.2.0",
|
||||||
|
"plist": "^3.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"slash": {
|
"slash": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
||||||
|
@ -7569,6 +7625,11 @@
|
||||||
"extend-shallow": "^3.0.0"
|
"extend-shallow": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sprintf-js": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug=="
|
||||||
|
},
|
||||||
"sshpk": {
|
"sshpk": {
|
||||||
"version": "1.16.1",
|
"version": "1.16.1",
|
||||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
|
||||||
|
@ -7641,6 +7702,11 @@
|
||||||
"readable-stream": "^2.0.2"
|
"readable-stream": "^2.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"stream-buffers": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz",
|
||||||
|
"integrity": "sha1-kdX1Ew0c75bc+n9yaUUYh0HQnuQ="
|
||||||
|
},
|
||||||
"stream-each": {
|
"stream-each": {
|
||||||
"version": "1.2.3",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz",
|
||||||
|
@ -9082,6 +9148,16 @@
|
||||||
"async-limiter": "~1.0.0"
|
"async-limiter": "~1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"xmlbuilder": {
|
||||||
|
"version": "9.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
|
||||||
|
"integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0="
|
||||||
|
},
|
||||||
|
"xmldom": {
|
||||||
|
"version": "0.1.31",
|
||||||
|
"resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz",
|
||||||
|
"integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ=="
|
||||||
|
},
|
||||||
"xtend": {
|
"xtend": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
"@nativescript-community/ui-material-progress": "^5.0.30",
|
"@nativescript-community/ui-material-progress": "^5.0.30",
|
||||||
"@nativescript-community/ui-material-ripple": "^5.0.30",
|
"@nativescript-community/ui-material-ripple": "^5.0.30",
|
||||||
"@nativescript/core": "~7.0.0",
|
"@nativescript/core": "~7.0.0",
|
||||||
|
"@nativescript/localize": "^5.0.2",
|
||||||
"@nativescript/social-share": "^2.0.1",
|
"@nativescript/social-share": "^2.0.1",
|
||||||
"@nativescript/theme": "^3.0.0",
|
"@nativescript/theme": "^3.0.0",
|
||||||
"@nativescript/zip": "^5.0.0",
|
"@nativescript/zip": "^5.0.0",
|
||||||
|
|