replaced mdripple

This commit is contained in:
vishnuraghavb 2021-02-28 20:40:26 +05:30
parent 89f8557521
commit 2b8627959b
16 changed files with 17165 additions and 3242 deletions

View file

@ -1,6 +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"; // Override variables here @import '~@nativescript/theme/core'; // Override variables here
$gray0: #fff; $gray0: #fff;
$gray1: #f0f0f0; $gray1: #f0f0f0;
$gray2: #e0e0e0; $gray2: #e0e0e0;
@ -10,7 +10,7 @@ $gray5: #858585;
$gray6: #575757; $gray6: #575757;
$gray7: #393939; $gray7: #393939;
$gray8: #292929; $gray8: #292929;
$gray9: #1A1A1A; $gray9: #1a1a1a;
$gray10: #000; $gray10: #000;
$orange: #ff5200; $orange: #ff5200;
$fabRipple: #ffa94d; $fabRipple: #ffa94d;
@ -265,7 +265,7 @@ ActionBar {
&.selected { &.selected {
color: $orange; color: $orange;
background: rgba($orange, 0.1); background: rgba($orange, 0.1);
MDRipple { .mdr {
ripple-color: transparent; ripple-color: transparent;
} }
} }
@ -278,7 +278,7 @@ ActionBar {
padding: 0 0 0 16; padding: 0 0 0 16;
} }
} }
MDRipple { .mdr {
padding: 0 16; padding: 0 16;
} }
MDButton.er { MDButton.er {
@ -306,7 +306,7 @@ ActionBar {
text-align: center; text-align: center;
margin: 8; margin: 8;
} }
MDRipple { .mdr {
border-radius: 4; border-radius: 4;
} }
MDButton { MDButton {
@ -322,7 +322,7 @@ MDButton {
} }
} }
MDButton, MDButton,
MDRipple { .mdr {
ripple-color: rgba($gray5, 0.2); ripple-color: rgba($gray5, 0.2);
} }
// ----------------------------- // -----------------------------

View file

@ -1,32 +1,83 @@
<template> <template>
<Page @loaded="onPageLoad" actionBarHidden="true" :androidStatusBarBackground="appTheme == 'Light' ? '#f0f0f0' : '#1A1A1A'"> <Page
@loaded="onPageLoad"
<Drawer @loaded="drawerLoad" :gestureEnabled="gestures" leftSwipeDistance="128"> actionBarHidden="true"
:androidStatusBarBackground="appTheme == 'Light' ? '#f0f0f0' : '#1A1A1A'"
>
<Drawer
@loaded="drawerLoad"
:gestureEnabled="gestures"
leftSwipeDistance="128"
>
<GridLayout ~leftDrawer rows="*, auto" columns="*" width="280" class="sd"> <GridLayout ~leftDrawer rows="*, auto" columns="*" width="280" class="sd">
<StackLayout row="0"> <StackLayout row="0">
<GridLayout rows="48" columns="auto, *, auto" v-for="(item, index) in topmenu" :key="index" class="sd-item orkm" :class="{ <GridLayout
'selected': currentComponent === item.component, rows="48"
}"> columns="auto, *, auto"
<MDRipple colSpan="3" @tap="navigateTo(item.component, item.component, false)" /> v-for="(item, index) in topmenu"
:key="index"
class="sd-item orkm mdr"
:class="{
selected: currentComponent === item.component,
}"
@tap="navigateTo(item.component, item.component, false)"
>
<Label col="0" class="er" :text="icon[item.icon]" /> <Label col="0" class="er" :text="icon[item.icon]" />
<Label col="1" :text="`${item.title}` | L" /> <Label col="1" :text="`${item.title}` | L" />
<Label class="recipeCount" v-if="getRecipeCount(item.title)" :text="getRecipeCount(item.title)" col="2" /> <Label
class="recipeCount"
v-if="getRecipeCount(item.title)"
:text="getRecipeCount(item.title)"
col="2"
/>
</GridLayout> </GridLayout>
<GridLayout class="sd-group-header orkm" rows="auto" columns="*, auto" v-if="cuisinesWithRecipes.length"> <GridLayout
<Label class="filterPath" verticalAlignment="center" col="0" :text="getCurrentPath | L" textWrap='true' /> class="sd-group-header orkm"
<MDButton :visibility="selectedCuisine?'visible':'hidden'" variant="text" @tap="previousRecipeFilter" class="er" col="2" :text="icon.back" /> rows="auto"
columns="*, auto"
v-if="cuisinesWithRecipes.length"
>
<Label
class="filterPath"
verticalAlignment="center"
col="0"
:text="getCurrentPath | L"
textWrap="true"
/>
<MDButton
:visibility="selectedCuisine ? 'visible' : 'hidden'"
variant="text"
@tap="previousRecipeFilter"
class="er"
col="2"
:text="icon.back"
/>
</GridLayout> </GridLayout>
<ScrollView height="100%"> <ScrollView height="100%">
<StackLayout> <StackLayout>
<GridLayout v-for="(item, index) in getRecipeList" :key="index" class="sd-item orkm" :class="{ <GridLayout
'selected': selectedTag == item, v-for="(item, index) in getRecipeList"
}" columns="auto, *, auto"> :key="index"
<MDRipple colSpan="3" @tap="setFilter && setRecipeFilter(item)" /> class="sd-item orkm mdr"
:class="{
selected: selectedTag == item,
}"
columns="auto, *, auto"
@tap="setFilter && setRecipeFilter(item)"
>
<Label col="0" class="er" :text="icon[selectedFilterType]" /> <Label col="0" class="er" :text="icon[selectedFilterType]" />
<Label col="1" :text="`${item}` | L" /> <Label col="1" :text="`${item}` | L" />
<Label class="recipeCount" :text="getRecipeCount(item)" col="2" /> <Label
class="recipeCount"
:text="getRecipeCount(item)"
col="2"
/>
</GridLayout> </GridLayout>
<GridLayout v-if="selectedFilterType =='tag' && !tagsWithRecipes.length" columns="*" rows="*"> <GridLayout
v-if="selectedFilterType == 'tag' && !tagsWithRecipes.length"
columns="*"
rows="*"
>
<Label class="noTags" :text="'noTs' | L" textWrap="true" /> <Label class="noTags" :text="'noTs' | L" textWrap="true" />
</GridLayout> </GridLayout>
</StackLayout> </StackLayout>
@ -34,44 +85,75 @@
</StackLayout> </StackLayout>
<StackLayout row="1"> <StackLayout row="1">
<StackLayout class="hr" margin="0 8 8"></StackLayout> <StackLayout class="hr" margin="0 8 8"></StackLayout>
<GridLayout rows="48" columns="auto, *" class="sd-item orkm" :class="{ <GridLayout
'selected': currentComponent == 'MealPlanner', rows="48"
}"> columns="auto, *"
<MDRipple row="0" colSpan="3" @tap="navigateTo(MealPlanner, 'MealPlanner', true)" /> class="sd-item orkm mdr"
:class="{
selected: currentComponent == 'MealPlanner',
}"
@tap="navigateTo(MealPlanner, 'MealPlanner', true)"
>
<Label col="0" class="er" :text="icon.cal" /> <Label col="0" class="er" :text="icon.cal" />
<Label col="2" :text="'planner' | L" /> <Label col="2" :text="'planner' | L" />
</GridLayout> </GridLayout>
<!-- <GridLayout rows="48" columns="auto, *" class="sd-item orkm" :class="{ <!-- <GridLayout
'selected': currentComponent == 'GroceryList', rows="48"
}"> columns="auto, *"
<MDRipple row="0" colSpan="3" @tap="navigateTo(GroceryList, 'GroceryList', true)" /> class="sd-item orkm mdr"
:class="{
selected: currentComponent == 'GroceryList',
}"
@tap="navigateTo(GroceryList, 'GroceryList', true)"
>
<Label col="0" class="er" :text="icon.bag" /> <Label col="0" class="er" :text="icon.bag" />
<Label col="2" :text="'grocery' | L" /> <Label col="2" :text="'grocery' | L" />
</GridLayout> </GridLayout>
<GridLayout rows="48" columns="auto, *" class="sd-item orkm" :class="{ <GridLayout
'selected': currentComponent == 'GroceryList', rows="48"
}"> columns="auto, *"
<MDRipple row="0" colSpan="3" @tap="navigateTo(GroceryList, 'GroceryList', true)" /> class="sd-item orkm mdr"
:class="{
selected: currentComponent == 'GroceryList',
}"
@tap="navigateTo(GroceryList, 'GroceryList', true)"
>
<Label col="0" class="er" :text="icon.price" /> <Label col="0" class="er" :text="icon.price" />
<Label col="2" :text="'Price List' | L" /> <Label col="2" :text="'Price List' | L" />
</GridLayout> --> </GridLayout> -->
<StackLayout class="hr" margin="8"></StackLayout> <StackLayout class="hr" margin="8"></StackLayout>
<GridLayout class="sd-item orkm" :class="{ <GridLayout
'selected': currentComponent == 'Settings', class="sd-item orkm mdr"
}" rows="48" columns="auto, *"> :class="{
<MDRipple colSpan="3" @tap="navigateTo(Settings, 'Settings', true)" /> selected: currentComponent == 'Settings',
}"
rows="48"
columns="auto, *"
@tap="navigateTo(Settings, 'Settings', true)"
>
<Label class="er" col="0" :text="icon.cog" /> <Label class="er" col="0" :text="icon.cog" />
<Label col="2" :text="'Settings' | L" /> <Label col="2" :text="'Settings' | L" />
</GridLayout> </GridLayout>
</StackLayout> </StackLayout>
</GridLayout> </GridLayout>
<Frame ~mainContent id="main-frame"> <Frame ~mainContent id="main-frame">
<EnRecipes ref="enrecipes" :filterFavourites="filterFavourites" :filterTrylater="filterTrylater" :selectedCuisine="selectedCuisine" :selectedCategory="selectedCategory" :selectedTag="selectedTag" :closeDrawer="closeDrawer" <EnRecipes
:hijackGlobalBackEvent="hijackGlobalBackEvent" :releaseGlobalBackEvent="releaseGlobalBackEvent" @backToHome="backToHome" :showDrawer="showDrawer" @selectModeOn="selectModeOn" /> ref="enrecipes"
:filterFavourites="filterFavourites"
:filterTrylater="filterTrylater"
:selectedCuisine="selectedCuisine"
:selectedCategory="selectedCategory"
:selectedTag="selectedTag"
:closeDrawer="closeDrawer"
:hijackGlobalBackEvent="hijackGlobalBackEvent"
:releaseGlobalBackEvent="releaseGlobalBackEvent"
@backToHome="backToHome"
:showDrawer="showDrawer"
@selectModeOn="selectModeOn"
/>
</Frame> </Frame>
</Drawer> </Drawer>
</Page> </Page>
@ -82,24 +164,16 @@ import {
ApplicationSettings, ApplicationSettings,
AndroidApplication, AndroidApplication,
Application, Application,
} } from "@nativescript/core";
from "@nativescript/core" import Theme from "@nativescript/theme";
import Theme from "@nativescript/theme" import { localize } from "@nativescript/localize";
import { import { mapActions, mapState } from "vuex";
localize import EnRecipes from "./EnRecipes";
} import ViewRecipe from "./ViewRecipe";
from "@nativescript/localize" import MealPlanner from "./MealPlanner";
import { import GroceryList from "./GroceryList";
mapActions, import Settings from "./Settings";
mapState import PromptDialog from "./modal/PromptDialog";
}
from "vuex"
import EnRecipes from "./EnRecipes"
import ViewRecipe from "./ViewRecipe"
import MealPlanner from "./MealPlanner"
import GroceryList from "./GroceryList"
import Settings from "./Settings"
import PromptDialog from "./modal/PromptDialog"
let filterTimer; let filterTimer;
export default { export default {
data() { data() {
@ -107,232 +181,316 @@ export default {
selectedCuisine: null, selectedCuisine: null,
selectedCategory: null, selectedCategory: null,
selectedTag: null, selectedTag: null,
selectedFilterType: 'cuisine', selectedFilterType: "cuisine",
filterFavourites: false, filterFavourites: false,
filterTrylater: false, filterTrylater: false,
MealPlanner: MealPlanner, MealPlanner: MealPlanner,
GroceryList: GroceryList, GroceryList: GroceryList,
Settings: Settings, Settings: Settings,
topmenu: [ { topmenu: [
{
title: "EnRecipes", title: "EnRecipes",
component: "EnRecipes", component: "EnRecipes",
icon: "home", icon: "home",
}, { },
{
title: "trylater", title: "trylater",
component: "Try Later", component: "Try Later",
icon: "try", icon: "try",
}, { },
{
title: "favourites", title: "favourites",
component: "Favourites", component: "Favourites",
icon: "fav", icon: "fav",
}, ], },
],
appTheme: "Light", appTheme: "Light",
setFilter: true, setFilter: true,
gestures: true, gestures: true,
drawer: null, drawer: null,
} };
}, },
components: { components: {
EnRecipes, EnRecipes,
ViewRecipe, ViewRecipe,
MealPlanner, MealPlanner,
GroceryList, GroceryList,
Settings Settings,
}, },
computed: { computed: {
...mapState( [ "icon", "recipes", "cuisines", "categories", "yieldUnits", "mealPlans", "currentComponent" ] ), ...mapState([
"icon",
"recipes",
"cuisines",
"categories",
"yieldUnits",
"mealPlans",
"currentComponent",
]),
getCurrentPath() { getCurrentPath() {
let path = "/" let path = "/";
if ( this.selectedCuisine ) path += localize( this.selectedCuisine ) if (this.selectedCuisine) path += localize(this.selectedCuisine);
else path = "cuis" else path = "cuis";
if ( this.selectedCategory ) path += "/" + localize( this.selectedCategory ) if (this.selectedCategory) path += "/" + localize(this.selectedCategory);
if ( this.selectedTag ) path += "/" + localize( this.selectedTag ) if (this.selectedTag) path += "/" + localize(this.selectedTag);
return path; return path;
}, },
getRecipeList() { getRecipeList() {
switch (this.selectedFilterType) { switch (this.selectedFilterType) {
case 'cuisine': case "cuisine":
return this.cuisinesWithRecipes return this.cuisinesWithRecipes;
break; break;
case 'category': case "category":
return this.categoriesWithRecipes return this.categoriesWithRecipes;
break; break;
case 'tag': case "tag":
return this.tagsWithRecipes return this.tagsWithRecipes;
break; break;
} }
}, },
cuisinesWithRecipes() { cuisinesWithRecipes() {
let arr = this.recipes.map( ( e ) => e.cuisine ).sort() let arr = this.recipes.map((e) => e.cuisine).sort();
return arr.length ? [ "allCuis", ...new Set( arr ) ] : [] return arr.length ? ["allCuis", ...new Set(arr)] : [];
}, },
categoriesWithRecipes() { categoriesWithRecipes() {
let arr = this.recipes.map( e => ( this.selectedCuisine === "allCuis" || e.cuisine === this.selectedCuisine ) && e.category ).filter( e => e ).sort() let arr = this.recipes
return arr.length ? [ "allCats", ...new Set( arr ) ] : [] .map(
(e) =>
(this.selectedCuisine === "allCuis" ||
e.cuisine === this.selectedCuisine) &&
e.category
)
.filter((e) => e)
.sort();
return arr.length ? ["allCats", ...new Set(arr)] : [];
}, },
tagsWithRecipes() { tagsWithRecipes() {
let arr = this.recipes.map( e => { let arr = this.recipes
if ( this.selectedCuisine === "allCuis" && this.selectedCategory === "allCats" && e.tags.length ) return e.tags; .map((e) => {
else if ( this.selectedCuisine === "allCuis" && e.category === this.selectedCategory && e.tags.length ) return e.tags; if (
else if ( this.selectedCategory === "allCats" && e.cuisine === this.selectedCuisine && e.tags.length ) return e.tags; this.selectedCuisine === "allCuis" &&
else if ( e.category === this.selectedCategory && e.cuisine === this.selectedCuisine && e.tags.length ) return e.tags; this.selectedCategory === "allCats" &&
} ).flat().filter( e => e ).sort() e.tags.length
let showAllTags = this.selectedCuisine === "allCuis" && this.selectedCategory === "allCats" )
return arr.length ? [ !showAllTags && "allTs", ...new Set( arr ) ].filter( e => e ) : [] return e.tags;
else if (
this.selectedCuisine === "allCuis" &&
e.category === this.selectedCategory &&
e.tags.length
)
return e.tags;
else if (
this.selectedCategory === "allCats" &&
e.cuisine === this.selectedCuisine &&
e.tags.length
)
return e.tags;
else if (
e.category === this.selectedCategory &&
e.cuisine === this.selectedCuisine &&
e.tags.length
)
return e.tags;
})
.flat()
.filter((e) => e)
.sort();
let showAllTags =
this.selectedCuisine === "allCuis" &&
this.selectedCategory === "allCats";
return arr.length
? [!showAllTags && "allTs", ...new Set(arr)].filter((e) => e)
: [];
}, },
}, },
methods: { methods: {
...mapActions( [ "setCurrentComponentAction", "initializeListItems", "initializeRecipes", "initializeMealPlans", "setShakeAction" ] ), ...mapActions([
"setCurrentComponentAction",
"initializeListItems",
"initializeRecipes",
"initializeMealPlans",
"setShakeAction",
]),
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);
} }
}, },
drawerLoad(args) { drawerLoad(args) {
this.drawer = args.object this.drawer = args.object;
}, },
// HELPERS // HELPERS
setRecipeFilter(item) { setRecipeFilter(item) {
this.setFilter = this.filterFavourites = this.filterTrylater = false this.setFilter = this.filterFavourites = this.filterTrylater = false;
this.$navigateBack({ this.$navigateBack({
frame: "main-frame", frame: "main-frame",
backstackVisible: false backstackVisible: false,
} ) });
setTimeout( e => { setTimeout((e) => {
if (this.selectedCuisine == null) { if (this.selectedCuisine == null) {
this.selectedCuisine = item this.selectedCuisine = item;
this.selectedFilterType = 'category' this.selectedFilterType = "category";
} else if (this.selectedCategory == null) { } else if (this.selectedCategory == null) {
this.selectedCategory = item this.selectedCategory = item;
this.selectedFilterType = 'tag' this.selectedFilterType = "tag";
if ( !this.tagsWithRecipes.length ) this.closeDrawer() if (!this.tagsWithRecipes.length) this.closeDrawer();
} else { } else {
this.selectedTag = item; this.selectedTag = item;
this.closeDrawer() this.closeDrawer();
} }
this.setFilter = true this.setFilter = true;
}, 250 ) }, 250);
this.setCurrentComponentAction( "Filtered recipes" ) this.setCurrentComponentAction("Filtered recipes");
}, },
previousRecipeFilter() { previousRecipeFilter() {
if (this.selectedCategory) { if (this.selectedCategory) {
this.selectedFilterType = 'category' this.selectedFilterType = "category";
this.selectedTag = this.selectedCategory = null this.selectedTag = this.selectedCategory = null;
this.setCurrentComponentAction( "Filtered recipes" ) this.setCurrentComponentAction("Filtered recipes");
} else { } else {
this.selectedFilterType = 'cuisine' this.selectedFilterType = "cuisine";
this.selectedCuisine = null this.selectedCuisine = null;
this.setCurrentComponentAction( "EnRecipes" ) this.setCurrentComponentAction("EnRecipes");
} }
}, },
showDrawer() { showDrawer() {
this.drawer.open() this.drawer.open();
}, },
closeDrawer() { closeDrawer() {
this.drawer.close() this.drawer.close();
}, },
getRecipeCount(arg) { getRecipeCount(arg) {
let count = '' let count = "";
switch (arg) { switch (arg) {
case 'EnRecipes': case "EnRecipes":
count = this.recipes.length count = this.recipes.length;
break; break;
case 'trylater': case "trylater":
count = this.recipes.filter( e => !e.tried ).length count = this.recipes.filter((e) => !e.tried).length;
break; break;
case 'favourites': case "favourites":
count = this.recipes.filter( e => e.isFavorite ).length count = this.recipes.filter((e) => e.isFavorite).length;
break; break;
default: { default: {
switch (this.selectedFilterType) { switch (this.selectedFilterType) {
case 'cuisine': case "cuisine":
count = this.recipes.filter( e => arg === "allCuis" ? e.cuisine : e.cuisine === arg ).length count = this.recipes.filter((e) =>
arg === "allCuis" ? e.cuisine : e.cuisine === arg
).length;
break; break;
case 'category': case "category":
count = this.recipes.filter( e => this.selectedCuisine === "allCuis" ? arg === "allCats" ? e.category : e.category === arg : arg === "allCats" ? e.cuisine === this.selectedCuisine && e.category : e.cuisine === this count = this.recipes.filter((e) =>
.selectedCuisine && e.category === arg ).length this.selectedCuisine === "allCuis"
? arg === "allCats"
? e.category
: e.category === arg
: arg === "allCats"
? e.cuisine === this.selectedCuisine && e.category
: e.cuisine === this.selectedCuisine && e.category === arg
).length;
break; break;
case 'tag': case "tag":
count = this.recipes.filter( e => { count = this.recipes.filter((e) => {
if ( this.selectedCuisine === "allCuis" && this.selectedCategory === "allCats" ) { if (
return e.tags.includes( arg ) || arg === "allTs" this.selectedCuisine === "allCuis" &&
} else if ( this.selectedCuisine === "allCuis" && e.category === this.selectedCategory ) { this.selectedCategory === "allCats"
return e.tags.includes( arg ) || arg === "allTs" ) {
} else if ( this.selectedCategory === "allCats" && e.cuisine === this.selectedCuisine ) { return e.tags.includes(arg) || arg === "allTs";
return e.tags.includes( arg ) || arg === "allTs" } else if (
} else if ( e.category === this.selectedCategory && e.cuisine === this.selectedCuisine ) { this.selectedCuisine === "allCuis" &&
return e.tags.includes( arg ) || arg === "allTs" e.category === this.selectedCategory
) {
return e.tags.includes(arg) || arg === "allTs";
} else if (
this.selectedCategory === "allCats" &&
e.cuisine === this.selectedCuisine
) {
return e.tags.includes(arg) || arg === "allTs";
} else if (
e.category === this.selectedCategory &&
e.cuisine === this.selectedCuisine
) {
return e.tags.includes(arg) || arg === "allTs";
} }
} ).length }).length;
break; break;
} }
} }
} }
return count return count;
}, },
selectModeOn(bool) { selectModeOn(bool) {
this.gestures = bool this.gestures = bool;
}, },
// NAVIGATION HANDLERS // NAVIGATION HANDLERS
hijackGlobalBackEvent() { hijackGlobalBackEvent() {
AndroidApplication.on( AndroidApplication.activityBackPressedEvent, this.globalBackEvent ) AndroidApplication.on(
AndroidApplication.activityBackPressedEvent,
this.globalBackEvent
);
}, },
releaseGlobalBackEvent() { releaseGlobalBackEvent() {
AndroidApplication.off( AndroidApplication.activityBackPressedEvent, this.globalBackEvent ) AndroidApplication.off(
AndroidApplication.activityBackPressedEvent,
this.globalBackEvent
);
}, },
globalBackEvent(args) { globalBackEvent(args) {
if (this.drawer && this.drawer.isOpened()) { if (this.drawer && this.drawer.isOpened()) {
args.cancel = true args.cancel = true;
this.closeDrawer() this.closeDrawer();
} else if ( } else if (
[ "Favourites", "Try Later", "Filtered recipes" ].includes( this.currentComponent ) ) { ["Favourites", "Try Later", "Filtered recipes"].includes(
args.cancel = true this.currentComponent
this.backToHome() )
) {
args.cancel = true;
this.backToHome();
} }
}, },
backToHome() { backToHome() {
this.setCurrentComponentAction( "EnRecipes" ) this.setCurrentComponentAction("EnRecipes");
this.filterFavourites = this.filterTrylater = false this.filterFavourites = this.filterTrylater = false;
this.selectedTag = this.selectedCategory = this.selectedCuisine = null this.selectedTag = this.selectedCategory = this.selectedCuisine = null;
this.selectedFilterType = "cuisine" this.selectedFilterType = "cuisine";
}, },
navigateTo(to, title, isTrueComponent) { navigateTo(to, title, isTrueComponent) {
if (title !== this.currentComponent) { if (title !== this.currentComponent) {
if (isTrueComponent) { if (isTrueComponent) {
this.$navigateTo(to, { this.$navigateTo(to, {
backstackVisible: true backstackVisible: true,
} ) });
this.closeDrawer() this.closeDrawer();
} else { } else {
this.setCurrentComponentAction( to ) this.setCurrentComponentAction(to);
this.$navigateBack({ this.$navigateBack({
frame: "main-frame", frame: "main-frame",
backstackVisible: false backstackVisible: false,
} ) });
this.filterFavourites = to === "Favourites" this.filterFavourites = to === "Favourites";
this.filterTrylater = to === "Try Later" this.filterTrylater = to === "Try Later";
this.closeDrawer() this.closeDrawer();
this.selectedTag = this.selectedCategory = this.selectedCuisine = null this.selectedTag = this.selectedCategory = this.selectedCuisine = null;
this.selectedFilterType = "cuisine" this.selectedFilterType = "cuisine";
} }
} else { } else {
this.closeDrawer() 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();
this.initializeListItems() this.initializeListItems();
if ( !this.mealPlans.length ) this.initializeMealPlans() if (!this.mealPlans.length) this.initializeMealPlans();
this.setShakeAction( ApplicationSettings.getBoolean( "shakeEnabled", true ) ) this.setShakeAction(ApplicationSettings.getBoolean("shakeEnabled", true));
}, },
} };
</script> </script>

View file

@ -1,66 +1,218 @@
<template> <template>
<Page @loaded="onPageLoad" @unloaded="onPageUnload"> <Page @loaded="onPageLoad" @unloaded="onPageUnload">
<ActionBar androidElevation="1"> <ActionBar androidElevation="1">
<GridLayout v-if="showSearch" columns="auto, *" verticalAlignment="center"> <GridLayout
<MDButton class="er" :text="icon.back" variant="text" automationText="Back" col="0" @tap="closeSearch" /> v-if="showSearch"
<SearchBar col="1" :hint="'ser' | L" @textChange="updateList($event.value)" @clear="clearSearch" /> columns="auto, *"
verticalAlignment="center"
>
<MDButton
class="er"
:text="icon.back"
variant="text"
automationText="Back"
col="0"
@tap="closeSearch"
/>
<SearchBar
col="1"
:hint="'ser' | L"
@textChange="updateList($event.value)"
@clear="clearSearch"
/>
</GridLayout> </GridLayout>
<GridLayout v-else columns="auto, *, auto, auto, auto"> <GridLayout v-else columns="auto, *, auto, auto, auto">
<MDButton class="er" col="0" variant="text" @tap="selectMode ? clearSelection() : showDrawer()" :text="selectMode ? icon.x : icon.menu" /> <MDButton
<Label v-if="selectMode" class="title orkm" :text="`${selection.length} ${$options.filters.L('sltd')}`" col="1" /> class="er"
<Label v-else class="title orkm" :text="`${currentComponent}` | L" col="1" /> col="0"
variant="text"
@tap="selectMode ? clearSelection() : showDrawer()"
:text="selectMode ? icon.x : icon.menu"
/>
<Label
v-if="selectMode"
class="title orkm"
:text="`${selection.length} ${$options.filters.L('sltd')}`"
col="1"
/>
<Label
v-else
class="title orkm"
:text="`${currentComponent}` | L"
col="1"
/>
<!-- <MDButton v-if="recipes.length" class="er" :text="layout== 1 ? icon.l1 : layout==2 ? icon.l2 : icon.l3" variant="text" col="2" @tap="switchLayout" /> --> <!-- <MDButton v-if="recipes.length" class="er" :text="layout== 1 ? icon.l1 : layout==2 ? icon.l2 : icon.l3" variant="text" col="2" @tap="switchLayout" /> -->
<MDButton v-if="recipes.length && !selectMode" class="er" :text="selectMode ? icon.export : icon.sear" variant="text" col="3" @tap="selectMode ? exportSelection() : openSearch()" /> <MDButton
<MDButton v-if="recipes.length" class="er" :text="selectMode ? icon.del : icon.sort" variant="text" col="4" @tap="selectMode ? deleteSelection() : sortDialog()" /> v-if="recipes.length && !selectMode"
class="er"
:text="selectMode ? icon.export : icon.sear"
variant="text"
col="3"
@tap="selectMode ? exportSelection() : openSearch()"
/>
<MDButton
v-if="recipes.length"
class="er"
:text="selectMode ? icon.del : icon.sort"
variant="text"
col="4"
@tap="selectMode ? deleteSelection() : sortDialog()"
/>
</GridLayout> </GridLayout>
</ActionBar> </ActionBar>
<AbsoluteLayout> <AbsoluteLayout>
<ListView width="100%" height="100%" for="recipe in filteredRecipes" @loaded="listViewLoad" :itemTemplateSelector="getLayout"> <ListView
width="100%"
height="100%"
for="recipe in filteredRecipes"
@loaded="listViewLoad"
:itemTemplateSelector="getLayout"
>
<v-template key="one"> <v-template key="one">
<GridLayout class="recipeContainer" :class="isFirstItem(recipe.id)"> <GridLayout class="recipeContainer" :class="isFirstItem(recipe.id)">
<GridLayout class="recipeItem layout1" rows="104" columns="104, *" androidElevation="1"> <GridLayout
<MDRipple colSpan="2" ref="recipe" @longPress="selectMode? viewRecipe(recipe.id) : addToSelection($event, recipe.id)" @tap="selectMode? addToSelection($event, recipe.id) : viewRecipe(recipe.id)" /> class="recipeItem layout1 mdr"
rows="104"
columns="104, *"
androidElevation="1"
ref="recipe"
@longPress="
selectMode
? viewRecipe(recipe.id)
: addToSelection($event, recipe.id)
"
@tap="
selectMode
? addToSelection($event, recipe.id)
: viewRecipe(recipe.id)
"
>
<GridLayout class="imageHolder card" rows="104" columns="104"> <GridLayout class="imageHolder card" rows="104" columns="104">
<Image row="0" col="0" v-if="recipe.imageSrc" :src="recipe.imageSrc" stretch="aspectFill" decodeWidth="104" decodeHeight="104" loadMode="async" /> <Image
<Label v-else row="0" col="0" horizontalAlignment="center" class="er" fontSize="56" :text="icon.img" /> row="0"
col="0"
v-if="recipe.imageSrc"
:src="recipe.imageSrc"
stretch="aspectFill"
decodeWidth="104"
decodeHeight="104"
loadMode="async"
/>
<Label
v-else
row="0"
col="0"
horizontalAlignment="center"
class="er"
fontSize="56"
:text="icon.img"
/>
</GridLayout> </GridLayout>
<StackLayout class="recipeInfo" col="1"> <StackLayout class="recipeInfo" col="1">
<Label :text="`${$options.filters.L(recipe.cuisine)} • ${$options.filters.L(recipe.category)}`" class="category" /> <Label
:text="`${$options.filters.L(
recipe.cuisine
)} ${$options.filters.L(recipe.category)}`"
class="category"
/>
<Label :text="recipe.title" class="orkm title" /> <Label :text="recipe.title" class="orkm title" />
<GridLayout columns="*" rows="auto, *, auto"> <GridLayout columns="*" rows="auto, *, auto">
<StackLayout class="attrContainer" orientation="horizontal" row="0"> <StackLayout
class="attrContainer"
orientation="horizontal"
row="0"
>
<Label class="er small" :text="icon.star" /> <Label class="er small" :text="icon.star" />
<Label class="attr" :text="recipe.rating" /> <Label class="attr" :text="recipe.rating" />
<Label class="er small" :text="icon.diff" /> <Label class="er small" :text="icon.diff" />
<Label class="attr" :text="`${recipe.difficulty}` | L" /> <Label class="attr" :text="`${recipe.difficulty}` | L" />
<Label class="er small" :text="icon.time" /> <Label class="er small" :text="icon.time" />
<Label class="attr" :text=" <Label
`${ class="attr"
formattedTotalTime(recipe.prepTime, recipe.cookTime).time :text="`${
}` formattedTotalTime(recipe.prepTime, recipe.cookTime)
" /> .time
}`"
/>
</StackLayout> </StackLayout>
<StackLayout class="tagsContainer" orientation="horizontal" row="2"> <StackLayout
<Label v-for="(tag, index) in recipe.tags" :key="index" class="tag" :text="tag" /> class="tagsContainer"
orientation="horizontal"
row="2"
>
<Label
v-for="(tag, index) in recipe.tags"
:key="index"
class="tag"
:text="tag"
/>
</StackLayout> </StackLayout>
</GridLayout> </GridLayout>
</StackLayout> </StackLayout>
</GridLayout> </GridLayout>
</GridLayout> </GridLayout>
</v-template> </v-template>
<!-- <v-template key="two"> <!-- <v-template key="two">
<GridLayout class="recipeContainer" :class="isFirstItem(recipe.id)"> <GridLayout class="recipeContainer" :class="isFirstItem(recipe.id)">
<GridLayout class="recipeItem layout2" rows="auto, auto" columns="*" androidElevation="1"> <GridLayout
<MDRipple rowSpan="2" ref="recipe" @longPress="selectMode? viewRecipe(recipe.id) : addToSelection($event, recipe.id)" @tap="selectMode? addToSelection($event, recipe.id) : viewRecipe(recipe.id)" /> class="recipeItem layout2 mdr"
rows="auto, auto"
columns="*"
androidElevation="1"
ref="recipe"
@longPress="
selectMode
? viewRecipe(recipe.id)
: addToSelection($event, recipe.id)
"
@tap="
selectMode
? addToSelection($event, recipe.id)
: viewRecipe(recipe.id)
"
>
<GridLayout class="imageHolder card" :rows="imgWidth" columns="*"> <GridLayout class="imageHolder card" :rows="imgWidth" columns="*">
<Image row="0" col="0" v-if="recipe.imageSrc" :src="recipe.imageSrc" stretch="aspectFill" :decodeWidth="imgWidth" :decodeHeight="imgWidth" loadMode="async" /> <Image
<Label v-else row="0" col="0" horizontalAlignment="center" class="er" :fontSize="imgWidth / 2" :text="icon.img" /> row="0"
col="0"
v-if="recipe.imageSrc"
:src="recipe.imageSrc"
stretch="aspectFill"
:decodeWidth="imgWidth"
:decodeHeight="imgWidth"
loadMode="async"
/>
<Label
v-else
row="0"
col="0"
horizontalAlignment="center"
class="er"
:fontSize="imgWidth / 2"
:text="icon.img"
/>
</GridLayout> </GridLayout>
<StackLayout class="recipeInfo" row="1"> <StackLayout class="recipeInfo" row="1">
<Label :text="`${$options.filters.L(recipe.cuisine)} • ${$options.filters.L(recipe.category)}`" class="category" /> <Label
:text="`${$options.filters.L(
recipe.cuisine
)} ${$options.filters.L(recipe.category)}`"
class="category"
/>
<Label :text="recipe.title" class="orkm title" /> <Label :text="recipe.title" class="orkm title" />
<StackLayout class="tagsContainer" orientation="horizontal" row="2"> <StackLayout
<Label v-for="(tag, index) in recipe.tags" :key="index" v-if="tag" class="tag" :text="tag" /> class="tagsContainer"
orientation="horizontal"
row="2"
>
<Label
v-for="(tag, index) in recipe.tags"
:key="index"
v-if="tag"
class="tag"
:text="tag"
/>
</StackLayout> </StackLayout>
</StackLayout> </StackLayout>
</GridLayout> </GridLayout>
@ -68,13 +220,39 @@
</v-template> </v-template>
<v-template key="three"> <v-template key="three">
<GridLayout class="recipeContainer" :class="isFirstItem(recipe.id)"> <GridLayout class="recipeContainer" :class="isFirstItem(recipe.id)">
<GridLayout class="recipeItem layout1" rows="auto" columns="*" androidElevation="1"> <GridLayout
<MDRipple ref="recipe" @longPress="selectMode? viewRecipe(recipe.id) : addToSelection($event, recipe.id)" @tap="selectMode? addToSelection($event, recipe.id) : viewRecipe(recipe.id)" /> class="recipeItem layout1 mdr"
rows="auto"
columns="*"
androidElevation="1"
ref="recipe"
@longPress="
selectMode
? viewRecipe(recipe.id)
: addToSelection($event, recipe.id)
"
@tap="
selectMode
? addToSelection($event, recipe.id)
: viewRecipe(recipe.id)
"
>
<StackLayout class="recipeInfo"> <StackLayout class="recipeInfo">
<Label :text="`${$options.filters.L(recipe.cuisine)} • ${$options.filters.L(recipe.category)}`" class="category" /> <Label
:text="`${$options.filters.L(
recipe.cuisine
)} ${$options.filters.L(recipe.category)}`"
class="category"
/>
<Label :text="recipe.title" class="orkm title" /> <Label :text="recipe.title" class="orkm title" />
<StackLayout class="tagsContainer" orientation="horizontal"> <StackLayout class="tagsContainer" orientation="horizontal">
<Label v-for="(tag, index) in recipe.tags" :key="index" v-if="tag" class="tag" :text="tag" /> <Label
v-for="(tag, index) in recipe.tags"
:key="index"
v-if="tag"
class="tag"
:text="tag"
/>
</StackLayout> </StackLayout>
</StackLayout> </StackLayout>
</GridLayout> </GridLayout>
@ -82,36 +260,66 @@
</v-template> --> </v-template> -->
</ListView> </ListView>
<GridLayout rows="*, auto, *, 88" columns="*" class="emptyStateContainer"> <GridLayout rows="*, auto, *, 88" columns="*" class="emptyStateContainer">
<StackLayout row="1" class="emptyState" v-if=" <StackLayout
!recipes.length && row="1"
!filterFavourites && class="emptyState"
!filterTrylater v-if="!recipes.length && !filterFavourites && !filterTrylater"
" @tap="addRecipe"> @tap="addRecipe"
>
<Label class="er icon" :text="icon.plusc" /> <Label class="er icon" :text="icon.plusc" />
<Label class="title orkm" :text="'strAdd' | L" textWrap="true" /> <Label class="title orkm" :text="'strAdd' | L" textWrap="true" />
<StackLayout orientation="horizontal" horizontalAlignment="center"> <StackLayout orientation="horizontal" horizontalAlignment="center">
<Label :text="'plsAdd' | L" textWrap="true" /> <Label :text="'plsAdd' | L" textWrap="true" />
</StackLayout> </StackLayout>
</StackLayout> </StackLayout>
<StackLayout row="1" class="emptyState" v-if="!filteredRecipes.length && filterTrylater && !searchQuery"> <StackLayout
row="1"
class="emptyState"
v-if="!filteredRecipes.length && filterTrylater && !searchQuery"
>
<Label class="er icon" :text="icon.try" textWrap="true" /> <Label class="er icon" :text="icon.try" textWrap="true" />
<Label class="title orkm" :text="'aD' | L" textWrap="true" /> <Label class="title orkm" :text="'aD' | L" textWrap="true" />
<Label :text="'tLInfo' | L" textWrap="true" /> <Label :text="'tLInfo' | L" textWrap="true" />
</StackLayout> </StackLayout>
<StackLayout row="1" class="emptyState" v-if="!filteredRecipes.length && filterFavourites && !searchQuery"> <StackLayout
row="1"
class="emptyState"
v-if="!filteredRecipes.length && filterFavourites && !searchQuery"
>
<Label class="er icon" :text="icon.fav" textWrap="true" /> <Label class="er icon" :text="icon.fav" textWrap="true" />
<Label class="title orkm" :text="'noFavs' | L" textWrap="true" /> <Label class="title orkm" :text="'noFavs' | L" textWrap="true" />
<Label :text="'fsList' | L" textWrap="true" /> <Label :text="'fsList' | L" textWrap="true" />
</StackLayout> </StackLayout>
<StackLayout row="1" class="emptyState" v-if="!filteredRecipes.length && searchQuery"> <StackLayout
row="1"
class="emptyState"
v-if="!filteredRecipes.length && searchQuery"
>
<Label class="er icon" :text="icon.noresult" textWrap="true" /> <Label class="er icon" :text="icon.noresult" textWrap="true" />
<Label class="title orkm" :text="`${noResultFor}` | L" textWrap="true" /> <Label
<MDButton v-if="filterFavourites || filterTrylater || selectedCuisine" variant="text" class="searchAll orkm" :text="'trySer' | L" @tap="searchAll" /> class="title orkm"
:text="`${noResultFor}` | L"
textWrap="true"
/>
<MDButton
v-if="filterFavourites || filterTrylater || selectedCuisine"
variant="text"
class="searchAll orkm"
:text="'trySer' | L"
@tap="searchAll"
/>
</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 v-if="showFAB" row="1" col="1" class="er fab-button" src="res://plus" @tap="addRecipe" /> <MDFloatingActionButton
v-if="showFAB"
row="1"
col="1"
class="er fab-button"
src="res://plus"
@tap="addRecipe"
/>
</transition> </transition>
</GridLayout> </GridLayout>
</AbsoluteLayout> </AbsoluteLayout>
@ -124,29 +332,17 @@ import {
Utils, Utils,
Observable, Observable,
Device, Device,
Screen Screen,
} } from "@nativescript/core";
from "@nativescript/core"; import { localize } from "@nativescript/localize";
import { import { time } from "tns-core-modules/profiling";
localize
}
from "@nativescript/localize"
import {
time
} from "tns-core-modules/profiling"
import { import {
startAccelerometerUpdates, startAccelerometerUpdates,
stopAccelerometerUpdates, stopAccelerometerUpdates,
} from "nativescript-accelerometer" } from "nativescript-accelerometer";
import { import { Vibrate } from "nativescript-vibrate";
Vibrate
} from 'nativescript-vibrate';
let vibrator = new Vibrate(); let vibrator = new Vibrate();
import { import { mapActions, mapState } from "vuex";
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 ActionDialog from "./modal/ActionDialog.vue"; import ActionDialog from "./modal/ActionDialog.vue";
@ -157,10 +353,20 @@ let lastForce = 0;
let shakeCount = 0; let shakeCount = 0;
let typingTimer; let typingTimer;
export default { export default {
props: [ "filterFavourites", "filterTrylater", "closeDrawer", "showDrawer", "selectedCategory", "selectedCuisine", "selectedTag", "hijackGlobalBackEvent", "releaseGlobalBackEvent" ], props: [
"filterFavourites",
"filterTrylater",
"closeDrawer",
"showDrawer",
"selectedCategory",
"selectedCuisine",
"selectedTag",
"hijackGlobalBackEvent",
"releaseGlobalBackEvent",
],
components: { components: {
EditRecipe, EditRecipe,
ViewRecipe ViewRecipe,
}, },
data() { data() {
return { return {
@ -178,26 +384,63 @@ export default {
}; };
}, },
computed: { computed: {
...mapState( [ "sortType", "icon", "recipes", "currentComponent", "shakeEnabled" ] ), ...mapState([
"sortType",
"icon",
"recipes",
"currentComponent",
"shakeEnabled",
]),
filteredRecipes() { filteredRecipes() {
let ingredients = this.recipes.map( e => e.ingredients.map( f => f.item.toLowerCase() ).join() ).join() let ingredients = this.recipes
.map((e) => e.ingredients.map((f) => f.item.toLowerCase()).join())
.join();
let vm = this let vm = this;
function getIngredients(e) { function getIngredients(e) {
return e.ingredients.map( f => f.item.toLowerCase() ).join().includes( vm.searchQuery ); return e.ingredients
.map((f) => f.item.toLowerCase())
.join()
.includes(vm.searchQuery);
} }
// if ( this.filterDone ) { // if ( this.filterDone ) {
if (this.filterFavourites) { if (this.filterFavourites) {
return this.recipes.filter( e => e.isFavorite && ( e.title.toLowerCase().includes( this.searchQuery ) || getIngredients( e ) ) ).sort( this.sortFunction ) return this.recipes
.filter(
(e) =>
e.isFavorite &&
(e.title.toLowerCase().includes(this.searchQuery) ||
getIngredients(e))
)
.sort(this.sortFunction);
} else if (this.filterTrylater) { } else if (this.filterTrylater) {
return this.recipes.filter( e => !e.tried && ( e.title.toLowerCase().includes( this.searchQuery ) || getIngredients( e ) ) ).sort( this.sortFunction ) return this.recipes
.filter(
(e) =>
!e.tried &&
(e.title.toLowerCase().includes(this.searchQuery) ||
getIngredients(e))
)
.sort(this.sortFunction);
} else if (this.selectedCuisine) { } else if (this.selectedCuisine) {
return this.recipes.filter( e => { return this.recipes
return this.recipeFilter( e ) && ( e.title.toLowerCase().includes( this.searchQuery ) || getIngredients( e ) ) .filter((e) => {
} ).sort( this.sortFunction ) return (
this.recipeFilter(e) &&
(e.title.toLowerCase().includes(this.searchQuery) ||
getIngredients(e))
);
})
.sort(this.sortFunction);
} else { } else {
return this.recipes.filter( e => e.title.toLowerCase().includes( this.searchQuery ) || getIngredients( e ) ).sort( this.sortFunction ) return this.recipes
.filter(
(e) =>
e.title.toLowerCase().includes(this.searchQuery) ||
getIngredients(e)
)
.sort(this.sortFunction);
} }
// } else { // } else {
// return 0; // return 0;
@ -210,25 +453,35 @@ export default {
return "noRecs"; return "noRecs";
}, },
screenWidth() { screenWidth() {
return Screen.mainScreen.widthDIPs return Screen.mainScreen.widthDIPs;
}, },
imgWidth() { imgWidth() {
return Screen.mainScreen.widthDIPs / 2 - 20 return Screen.mainScreen.widthDIPs / 2 - 20;
}, },
}, },
methods: { methods: {
...mapActions( [ "setCurrentComponentAction", "setSortTypeAction", "deleteRecipeAction", "deleteRecipesAction" ] ), ...mapActions([
"setCurrentComponentAction",
"setSortTypeAction",
"deleteRecipeAction",
"deleteRecipesAction",
]),
onPageLoad(args) { onPageLoad(args) {
const page = args.object; const page = args.object;
page.bindingContext = new Observable(); page.bindingContext = new Observable();
this.filterFavourites ? this.setComponent( "Favourites" ) : this.filterTrylater ? this.setComponent( "Try Later" ) : this.selectedCuisine ? this.setComponent( "Filtered recipes" ) : this.setComponent( "EnRecipes" ) this.filterFavourites
if ( !this.selectMode ) this.showFAB = true ? this.setComponent("Favourites")
if ( this.shakeEnabled ) startAccelerometerUpdates( data => this.onSensorData( data ) ) : this.filterTrylater
if ( this.showSearch || this.selectMode ) ? this.setComponent("Try Later")
this.hijackLocalBackEvent() : this.selectedCuisine
this.showDrawer() ? this.setComponent("Filtered recipes")
this.closeDrawer() : this.setComponent("EnRecipes");
if (!this.selectMode) this.showFAB = true;
if (this.shakeEnabled)
startAccelerometerUpdates((data) => this.onSensorData(data));
if (this.showSearch || this.selectMode) this.hijackLocalBackEvent();
this.showDrawer();
this.closeDrawer();
}, },
onPageUnload() { onPageUnload() {
if (this.shakeEnabled) stopAccelerometerUpdates(); if (this.shakeEnabled) stopAccelerometerUpdates();
@ -236,8 +489,8 @@ export default {
this.releaseLocalBackEvent(); this.releaseLocalBackEvent();
}, },
listViewLoad(args) { listViewLoad(args) {
let e = args.object.android let e = args.object.android;
e.setSelector( new android.graphics.drawable.StateListDrawable() ) e.setSelector(new android.graphics.drawable.StateListDrawable());
e.setDivider(null); e.setDivider(null);
e.setDividerHeight(1); e.setDividerHeight(1);
}, },
@ -248,11 +501,11 @@ export default {
getLayout() { getLayout() {
switch (this.layout) { switch (this.layout) {
case 1: case 1:
return 'one'; return "one";
case 2: case 2:
return 'two'; return "two";
case 3: case 3:
return 'three'; return "three";
} }
}, },
@ -274,51 +527,58 @@ export default {
this.hijackGlobalBackEvent(); this.hijackGlobalBackEvent();
}, },
clearSearch() { clearSearch() {
this.searchQuery = "" this.searchQuery = "";
}, },
updateList(value) { updateList(value) {
clearTimeout( typingTimer ) clearTimeout(typingTimer);
typingTimer = setTimeout( e => { typingTimer = setTimeout((e) => {
this.searchQuery = value this.searchQuery = value;
}, 750 ) }, 750);
}, },
formattedTotalTime(prepTime, cookTime) { formattedTotalTime(prepTime, cookTime) {
let t1 = prepTime.split(":"); let t1 = prepTime.split(":");
let t2 = cookTime.split(":"); let t2 = cookTime.split(":");
let minutes = parseInt( t1[ 1 ] ) + parseInt( t2[ 1 ] ) let minutes = parseInt(t1[1]) + parseInt(t2[1]);
let m = minutes % 60 let m = minutes % 60;
let h = parseInt(t1[0]) + parseInt(t2[0]) + Math.floor(minutes / 60); let h = parseInt(t1[0]) + parseInt(t2[0]) + Math.floor(minutes / 60);
let hr = localize( 'hr' ) let hr = localize("hr");
let min = localize( 'min' ) let min = localize("min");
let mins = h * 60 + m let mins = h * 60 + m;
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: `${mins}` duration: `${mins}`,
}; };
}, },
randomRecipeID() { // TODO: show only from selected filter randomRecipeID() {
let min = 0 // TODO: show only from selected filter
let max = this.filteredRecipes.length - 1 let min = 0;
let randomIndex = Math.round( Math.random() * ( max - min ) ) let max = this.filteredRecipes.length - 1;
return this.filteredRecipes[ randomIndex ].id let randomIndex = Math.round(Math.random() * (max - min));
return this.filteredRecipes[randomIndex].id;
}, },
recipeFilter(e) { recipeFilter(e) {
let cuisineMatched = e.cuisine === this.selectedCuisine let cuisineMatched = e.cuisine === this.selectedCuisine;
let allCuisines = /allCuis/.test( this.selectedCuisine ) let allCuisines = /allCuis/.test(this.selectedCuisine);
let categoryMatched = e.category === this.selectedCategory let categoryMatched = e.category === this.selectedCategory;
let allCategories = /allCats/.test( this.selectedCategory ) let allCategories = /allCats/.test(this.selectedCategory);
let tagMatched = e.tags.includes( this.selectedTag ) let tagMatched = e.tags.includes(this.selectedTag);
let allTags = /allTs/.test( this.selectedTag ) let allTags = /allTs/.test(this.selectedTag);
let cuisine = cuisineMatched || allCuisines let cuisine = cuisineMatched || allCuisines;
return this.selectedTag && !allTags ? ( categoryMatched || allCategories ) && cuisine && tagMatched : this.selectedCategory && !allCategories ? cuisine && categoryMatched : cuisine return this.selectedTag && !allTags
? (categoryMatched || allCategories) && cuisine && tagMatched
: this.selectedCategory && !allCategories
? cuisine && categoryMatched
: cuisine;
}, },
searchAll() { searchAll() {
this.$emit( "backToHome" ) this.$emit("backToHome");
}, },
sortFunction(a, b) { sortFunction(a, b) {
const titleOrder = a.title.toLowerCase().localeCompare( b.title.toLowerCase(), Device.language, { const titleOrder = a.title
ignorePunctuation: true .toLowerCase()
.localeCompare(b.title.toLowerCase(), Device.language, {
ignorePunctuation: true,
}); });
let d1 = this.formattedTotalTime(a.prepTime, a.cookTime).duration; let d1 = this.formattedTotalTime(a.prepTime, a.cookTime).duration;
let d2 = this.formattedTotalTime(b.prepTime, b.cookTime).duration; let d2 = this.formattedTotalTime(b.prepTime, b.cookTime).duration;
@ -326,8 +586,8 @@ export default {
let ld2 = new Date(b.lastModified); let ld2 = new Date(b.lastModified);
let cd1 = new Date(a.created); let cd1 = new Date(a.created);
let cd2 = new Date(b.created); let cd2 = new Date(b.created);
let r1 = a.rating let r1 = a.rating;
let r2 = b.rating let r2 = b.rating;
function difficultyLevel(l) { function difficultyLevel(l) {
switch (l) { switch (l) {
@ -339,8 +599,8 @@ export default {
return 3; return 3;
} }
} }
let dl1 = difficultyLevel( a.difficulty ) let dl1 = difficultyLevel(a.difficulty);
let dl2 = difficultyLevel( b.difficulty ) let dl2 = difficultyLevel(b.difficulty);
switch (this.sortType) { switch (this.sortType) {
case "Title": case "Title":
return titleOrder > 0 ? 1 : titleOrder < 0 ? -1 : 0; return titleOrder > 0 ? 1 : titleOrder < 0 ? -1 : 0;
@ -369,33 +629,42 @@ export default {
} }
}, },
isFirstItem(id) { isFirstItem(id) {
let length = this.filteredRecipes.length let length = this.filteredRecipes.length;
return id == this.filteredRecipes[ 0 ].id ? 'firstItem' : id == this.filteredRecipes[ length - 1 ].id ? 'lastItem' : '' return id == this.filteredRecipes[0].id
? "firstItem"
: id == this.filteredRecipes[length - 1].id
? "lastItem"
: "";
}, },
isLastItem(id) { isLastItem(id) {
let length = this.filteredRecipes.length let length = this.filteredRecipes.length;
// let lastIsOdd = ( length - 1 ) % 2 == 0 // let lastIsOdd = ( length - 1 ) % 2 == 0
// if ( this.filteredRecipes.length > 1 ) { // if ( this.filteredRecipes.length > 1 ) {
// if ( id == this.filteredRecipes[ length - 2 ].id ) { // if ( id == this.filteredRecipes[ length - 2 ].id ) {
// if ( !lastIsOdd ) return 'lastItem' // if ( !lastIsOdd ) return 'lastItem'
// } // }
// } // }
if ( id == this.filteredRecipes[ length - 1 ].id ) return 'lastItem' if (id == this.filteredRecipes[length - 1].id) return "lastItem";
}, },
// NAVIGATION HANDLERS // NAVIGATION HANDLERS
hijackLocalBackEvent() { hijackLocalBackEvent() {
this.releaseGlobalBackEvent(); this.releaseGlobalBackEvent();
AndroidApplication.on( AndroidApplication.activityBackPressedEvent, this.localBackEvent ); AndroidApplication.on(
AndroidApplication.activityBackPressedEvent,
this.localBackEvent
);
}, },
releaseLocalBackEvent() { releaseLocalBackEvent() {
AndroidApplication.off( AndroidApplication.activityBackPressedEvent, this.localBackEvent ); AndroidApplication.off(
AndroidApplication.activityBackPressedEvent,
this.localBackEvent
);
this.hijackGlobalBackEvent(); this.hijackGlobalBackEvent();
}, },
localBackEvent(args) { localBackEvent(args) {
args.cancel = true; args.cancel = true;
if ( this.selectMode ) if (this.selectMode) this.clearSelection();
this.clearSelection()
this.closeDrawer(); this.closeDrawer();
this.closeSearch(); this.closeSearch();
}, },
@ -409,7 +678,7 @@ export default {
selectedTag: this.selectedTag, selectedTag: this.selectedTag,
filterFavourites: this.filterFavourites, filterFavourites: this.filterFavourites,
filterTrylater: this.filterTrylater, filterTrylater: this.filterTrylater,
} },
}); });
}, },
viewRecipe(recipeID) { viewRecipe(recipeID) {
@ -417,9 +686,9 @@ export default {
this.$navigateTo(ViewRecipe, { this.$navigateTo(ViewRecipe, {
props: { props: {
filterTrylater: this.filterTrylater, filterTrylater: this.filterTrylater,
recipeID recipeID,
}, },
backstackVisible: false backstackVisible: false,
}); });
}, },
viewRandomRecipe() { viewRandomRecipe() {
@ -427,9 +696,9 @@ export default {
this.$navigateTo(ViewRecipe, { this.$navigateTo(ViewRecipe, {
props: { props: {
filterTrylater: false, filterTrylater: false,
recipeID: this.randomRecipeID() recipeID: this.randomRecipeID(),
}, },
backstackVisible: false backstackVisible: false,
}); });
}, },
@ -439,15 +708,24 @@ export default {
this.$showModal(ActionDialog, { this.$showModal(ActionDialog, {
props: { props: {
title: "srt", title: "srt",
list: [ "Title", "Quickest first", "Slowest first", "Rating", "Difficulty level", "Last updated", "Newest first", "Oldest first" ], list: [
"Title",
"Quickest first",
"Slowest first",
"Rating",
"Difficulty level",
"Last updated",
"Newest first",
"Oldest first",
],
stretch: false, stretch: false,
helpIcon: 'sort', helpIcon: "sort",
bgColor: '#858585', bgColor: "#858585",
} },
} ).then( action => { }).then((action) => {
if (action && action !== "Cancel" && this.sortType !== action) { if (action && action !== "Cancel" && this.sortType !== action) {
this.setSortTypeAction( action ) this.setSortTypeAction(action);
ApplicationSettings.setString( "sortType", action ) ApplicationSettings.setString("sortType", action);
this.updateSort(); this.updateSort();
} }
this.hijackGlobalBackEvent(); this.hijackGlobalBackEvent();
@ -456,60 +734,58 @@ export default {
// DATA HANDLERS // DATA HANDLERS
addToSelection(args, id) { addToSelection(args, id) {
this.showFAB = false this.showFAB = false;
if ( !this.selectMode ) if (!this.selectMode) this.hijackLocalBackEvent();
this.hijackLocalBackEvent() this.selectMode = true;
this.selectMode = true this.$emit("selectModeOn", false);
this.$emit( "selectModeOn", false ) let item = args.object;
let item = args.object
if (item.className === "selected") { if (item.className === "selected") {
item.className = "" item.className = "";
this.selection.splice( this.selection.indexOf( id ), 1 ) this.selection.splice(this.selection.indexOf(id), 1);
this.recipeList.splice( this.selection.indexOf( id ), 1 ) this.recipeList.splice(this.selection.indexOf(id), 1);
} else { } else {
item.className = "selected" item.className = "selected";
this.selection.push( id ) this.selection.push(id);
this.recipeList.push( item ) this.recipeList.push(item);
} }
if ( !this.selection.length ) if (!this.selection.length) this.clearSelection();
this.clearSelection()
}, },
clearSelection() { clearSelection() {
this.selectMode = false this.selectMode = false;
this.$emit( "selectModeOn", true ) this.$emit("selectModeOn", true);
this.selection = [] this.selection = [];
this.recipeList.forEach( e => e.className = "" ) this.recipeList.forEach((e) => (e.className = ""));
this.releaseLocalBackEvent() this.releaseLocalBackEvent();
this.showFAB = true this.showFAB = true;
}, },
deleteSelection() { deleteSelection() {
this.selection.length === 1 ? this.selection.length === 1
this.deleteRecipe( this.selection[ 0 ] ) : ? this.deleteRecipe(this.selection[0])
this.deleteRecipes( this.selection ) : this.deleteRecipes(this.selection);
}, },
exportSelection() {}, exportSelection() {},
deleteRecipe(id) { deleteRecipe(id) {
this.deletionDialogActive = true; this.deletionDialogActive = true;
let index = this.recipes.findIndex( e => e.id === id ) let index = this.recipes.findIndex((e) => e.id === id);
this.$showModal(ConfirmDialog, { this.$showModal(ConfirmDialog, {
props: { props: {
title: localize("conf"), title: localize("conf"),
description: `${localize('delRecInfo')} "${this.recipes[index].title}"`, description: `${localize("delRecInfo")} "${
this.recipes[index].title
}"`,
cancelButtonText: "cBtn", cancelButtonText: "cBtn",
okButtonText: "dBtn", okButtonText: "dBtn",
helpIcon: 'del', helpIcon: "del",
bgColor: '#c92a2a', bgColor: "#c92a2a",
} },
} ).then( action => { }).then((action) => {
if (action) { if (action) {
this.deleteRecipeAction({ this.deleteRecipeAction({
index, index,
id id,
}); });
if ( !this.filteredRecipes.length ) if (!this.filteredRecipes.length) this.$emit("backToHome");
this.$emit( 'backToHome' ) this.clearSelection();
this.clearSelection()
} }
this.deletionDialogActive = false; this.deletionDialogActive = false;
}); });
@ -519,52 +795,51 @@ export default {
this.$showModal(ConfirmDialog, { this.$showModal(ConfirmDialog, {
props: { props: {
title: localize("conf"), title: localize("conf"),
description: `${localize('delRecsInfo')} ${this.selection.length} ${localize('recs')}`, description: `${localize("delRecsInfo")} ${
this.selection.length
} ${localize("recs")}`,
cancelButtonText: "cBtn", cancelButtonText: "cBtn",
okButtonText: "dBtn", okButtonText: "dBtn",
helpIcon: 'del', helpIcon: "del",
bgColor: '#c92a2a', bgColor: "#c92a2a",
} },
} ).then( action => { }).then((action) => {
if (action) { if (action) {
this.deleteRecipesAction(idsArr); this.deleteRecipesAction(idsArr);
if ( !this.filteredRecipes.length ) if (!this.filteredRecipes.length) this.$emit("backToHome");
this.$emit( 'backToHome' ) this.clearSelection();
this.clearSelection()
} }
this.deletionDialogActive = false; this.deletionDialogActive = false;
}); });
}, },
// SHAKE DETECTOR // SHAKE DETECTOR
onSensorData( { onSensorData({ x, y, z }) {
x, x = x.toFixed(2);
y, y = y.toFixed(2);
z z = z.toFixed(2);
} ) {
x = x.toFixed( 2 )
y = y.toFixed( 2 )
z = z.toFixed( 2 )
const FORCE_THRESHOLD = 1; const FORCE_THRESHOLD = 1;
const TIME_THRESHOLD = 150; const TIME_THRESHOLD = 150;
const SHAKE_TIMEOUT = 600; const SHAKE_TIMEOUT = 600;
const SHAKE_THROTTLE = 600; const SHAKE_THROTTLE = 600;
const SHAKE_COUNT = 3; const SHAKE_COUNT = 3;
const now = time() const now = time();
if ( ( now - lastForce ) > SHAKE_TIMEOUT ) { if (now - lastForce > SHAKE_TIMEOUT) {
shakeCount = 0; shakeCount = 0;
} }
let timeDelta = now - lastTime; let timeDelta = now - lastTime;
if (timeDelta > TIME_THRESHOLD) { if (timeDelta > TIME_THRESHOLD) {
let forceVector = Math.abs( Math.sqrt( Math.pow( x, 2 ) + Math.pow( y, 2 ) + Math.pow( z, 2 ) ) - 1 ); let forceVector = Math.abs(
Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2)) - 1
);
if (forceVector > FORCE_THRESHOLD) { if (forceVector > FORCE_THRESHOLD) {
shakeCount++; shakeCount++;
if ( ( shakeCount >= SHAKE_COUNT ) && ( now - lastShake > SHAKE_THROTTLE ) ) { if (shakeCount >= SHAKE_COUNT && now - lastShake > SHAKE_THROTTLE) {
lastShake = now; lastShake = now;
shakeCount = 0; shakeCount = 0;
if (this.filteredRecipes.length) { if (this.filteredRecipes.length) {
vibrator.vibrate( 100 ) vibrator.vibrate(100);
this.viewRandomRecipe() this.viewRandomRecipe();
} }
} }
lastForce = now; lastForce = now;
@ -574,7 +849,7 @@ export default {
}, },
}, },
mounted() { mounted() {
this.showFAB = true this.showFAB = true;
} },
} };
</script> </script>

View file

@ -2,57 +2,57 @@
<Page @loaded="onPageLoad"> <Page @loaded="onPageLoad">
<ActionBar flat="true"> <ActionBar flat="true">
<GridLayout rows="*" columns="auto, *, auto"> <GridLayout rows="*" columns="auto, *, auto">
<MDButton class="er left" variant="text" :text="icon.back" automationText="Back" @tap="$navigateBack()" col="0" /> <MDButton
class="er left"
variant="text"
:text="icon.back"
automationText="Back"
@tap="$navigateBack()"
col="0"
/>
<Label class="title orkm" :text="'grocery' | L" col="1" /> <Label class="title orkm" :text="'grocery' | L" col="1" />
<MDButton class="er left" variant="text" :text="icon.today" automationText="today" col="2" /> <MDButton
class="er left"
variant="text"
:text="icon.today"
automationText="today"
col="2"
/>
</GridLayout> </GridLayout>
</ActionBar> </ActionBar>
<GridLayout columns="" rows=""> <GridLayout columns="" rows=""> </GridLayout>
</GridLayout>
</Page> </Page>
</template> </template>
<script> <script>
import { import { ApplicationSettings, Observable } from "@nativescript/core";
ApplicationSettings, import { SnackBar } from "@nativescript-community/ui-material-snackbar";
Observable,
}
from "@nativescript/core"
import {
SnackBar
} from '@nativescript-community/ui-material-snackbar';
const snackbar = new SnackBar(); const snackbar = new SnackBar();
import { import { mapState, mapActions } from "vuex";
mapState,
mapActions
}
from "vuex"
export default { export default {
data() { data() {
return { return {
appTheme: "Light", appTheme: "Light",
} };
}, },
computed: { computed: {
...mapState(["icon", "recipes", "mealPlans"]), ...mapState(["icon", "recipes", "mealPlans"]),
isLightMode() { isLightMode() {
return this.appTheme === "Light" return this.appTheme === "Light";
}, },
}, },
methods: { methods: {
...mapActions(["setCurrentComponentAction"]), ...mapActions(["setCurrentComponentAction"]),
onPageLoad(args) { onPageLoad(args) {
const page = args.object; const page = args.object;
page.bindingContext = new Observable(); page.bindingContext = new Observable();
this.setCurrentComponentAction( "GroceryList" ) this.setCurrentComponentAction("GroceryList");
}, },
// HELPERS // HELPERS
// 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: {
@ -60,24 +60,23 @@ export default {
recipeID, recipeID,
}, },
backstackVisible: false, backstackVisible: false,
} ) });
} }
}, },
// DATA HANDLERS // DATA HANDLERS
undoRemove(message) { undoRemove(message) {
return snackbar return snackbar.action({
.action( {
message, message,
textColor: this.appTheme == "Light" ? "#fff" : "#292929", textColor: this.appTheme == "Light" ? "#fff" : "#292929",
actionTextColor: '#ff5200', actionTextColor: "#ff5200",
backgroundColor: this.appTheme == "Light" ? "#292929" : "#fff", backgroundColor: this.appTheme == "Light" ? "#292929" : "#fff",
actionText: 'Undo', actionText: "Undo",
hideDelay: 5000 hideDelay: 5000,
} ) });
}, },
}, },
created() { created() {
this.appTheme = ApplicationSettings.getString( "appTheme", "Light" ) this.appTheme = ApplicationSettings.getString("appTheme", "Light");
}, },
} };
</script> </script>

View file

@ -2,35 +2,140 @@
<Page @loaded="onPageLoad" @unloaded="onPageUnload"> <Page @loaded="onPageLoad" @unloaded="onPageUnload">
<ActionBar androidElevation="1"> <ActionBar androidElevation="1">
<GridLayout rows="*" columns="auto, *, auto, auto"> <GridLayout rows="*" columns="auto, *, auto, auto">
<MDButton class="er" variant="text" :text="icon.back" automationText="Back" @tap="$navigateBack()" col="0" /> <MDButton
class="er"
variant="text"
:text="icon.back"
automationText="Back"
@tap="$navigateBack()"
col="0"
/>
<Label class="title orkm" :text="'planner' | L" col="1" /> <Label class="title orkm" :text="'planner' | L" col="1" />
<MDButton class="er" variant="text" :text="icon.tod" automationText="today" @tap="goToToday" col="2" /> <MDButton
<MDButton class="er" variant="text" :text="edit ? icon.done : icon.edit" automationText="edit" @tap="edit = !edit" col="3" /> class="er"
variant="text"
:text="icon.tod"
automationText="today"
@tap="goToToday"
col="2"
/>
<MDButton
class="er"
variant="text"
:text="edit ? icon.done : icon.edit"
automationText="edit"
@tap="edit = !edit"
col="3"
/>
</GridLayout> </GridLayout>
</ActionBar> </ActionBar>
<ScrollView width="100%" height="100%"> <ScrollView width="100%" height="100%">
<GridLayout rows="auto, *"> <GridLayout rows="auto, *">
<GridLayout class="calendar" width="100%" row="0" columns="*, *, *, *, *, *, *" rows="auto, auto, auto, auto, auto, auto, auto, auto"> <GridLayout
<MDButton variant="text" class="er navBtn" col="0" :text="icon.left" @tap="prevMonth" /> class="calendar"
<Label class="monthName" col="1" colSpan="5" :text="$options.filters.L(mNames[month]) + ' ' + year" /> width="100%"
<MDButton variant="text" class="er navBtn" col="6" :text="icon.right" @tap="nextMonth" /> row="0"
<Label class="dayName" row="1" :col="i" v-for="(d,i) in dNames" :key="d" :text="$options.filters.L(d)" /> columns="*, *, *, *, *, *, *"
<Label @loaded="centerLabel" class="day orkm" :androidElevation="hasPlans(d) ? 1 : 0" :class="{'today': isToday(d), 'activeDay': isActive(d),'hasPlans': hasPlans(d)}" :row="getrow(i)" :col="i % 7" v-for="(d, i) in getCal" :key="i" rows="auto, auto, auto, auto, auto, auto, auto, auto"
:text="d ? d : null" @tap="setToday(d)" /> >
<MDButton
variant="text"
class="er navBtn"
col="0"
:text="icon.left"
@tap="prevMonth"
/>
<Label
class="monthName"
col="1"
colSpan="5"
:text="$options.filters.L(mNames[month]) + ' ' + year"
/>
<MDButton
variant="text"
class="er navBtn"
col="6"
:text="icon.right"
@tap="nextMonth"
/>
<Label
class="dayName"
row="1"
:col="i"
v-for="(d, i) in dNames"
:key="d"
:text="$options.filters.L(d)"
/>
<Label
@loaded="centerLabel"
class="day orkm"
:androidElevation="hasPlans(d) ? 1 : 0"
:class="{
today: isToday(d),
activeDay: isActive(d),
hasPlans: hasPlans(d),
}"
:row="getrow(i)"
:col="i % 7"
v-for="(d, i) in getCal"
:key="i"
:text="d ? d : null"
@tap="setToday(d)"
/>
</GridLayout> </GridLayout>
<StackLayout row="1" class="dayPlan"> <StackLayout row="1" class="dayPlan">
<StackLayout class="hr" margin="16 0 0"></StackLayout> <StackLayout class="hr" margin="16 0 0"></StackLayout>
<StackLayout v-for="(mealType, index) in mealTimes" :key="'mealType' + index" class="plansContainer" :class="mealType"> <StackLayout
v-for="(mealType, index) in mealTimes"
:key="'mealType' + index"
class="plansContainer"
:class="mealType"
>
<GridLayout columns="auto, auto" class="header"> <GridLayout columns="auto, auto" class="header">
<Label col="0" @tap="edit = true" class="periodLabel orkm" :text="mealType | L" /> <Label
<MDButton :visibility="edit ? 'visible' : 'hidden'" col="1" variant="text" class="er" :text="icon.plus" @tap="addRecipe(mealType)" /> col="0"
@tap="edit = true"
class="periodLabel orkm"
:text="mealType | L"
/>
<MDButton
:visibility="edit ? 'visible' : 'hidden'"
col="1"
variant="text"
class="er"
:text="icon.plus"
@tap="addRecipe(mealType)"
/>
</GridLayout> </GridLayout>
<GridLayout class="recipe" :paddingTop="index == 0?8:0" :columns="`*, ${edit ? 'auto' : 0}`" v-for="(recipeID, index) in getRecipes[mealType]" :key="mealType + index"> <GridLayout
<GridLayout androidElevation="1" col="0" columns="*" class="titleContainer"> class="recipe"
<MDRipple class="recipeRipple" @tap="viewRecipe(recipeID)" /> :paddingTop="index == 0 ? 8 : 0"
<Label verticalAlignment="center" class="recipeTitle" :text="getRecipeTitle(recipeID)" textWrap="true" /> :columns="`*, ${edit ? 'auto' : 0}`"
v-for="(recipeID, index) in getRecipes[mealType]"
:key="mealType + index"
>
<GridLayout
androidElevation="1"
col="0"
columns="*"
class="titleContainer mdr"
@tap="viewRecipe(recipeID)"
>
<Label
verticalAlignment="center"
class="recipeTitle"
:text="getRecipeTitle(recipeID)"
textWrap="true"
/>
</GridLayout> </GridLayout>
<MDButton :visibility="edit ? 'visible' : 'hidden'" variant="text" col="1" class="er x" :text="icon.x" @tap="removeRecipe(recipeID, mealType)" /> <MDButton
:visibility="edit ? 'visible' : 'hidden'"
variant="text"
col="1"
class="er x"
:text="icon.x"
@tap="removeRecipe(recipeID, mealType)"
/>
</GridLayout> </GridLayout>
</StackLayout> </StackLayout>
</StackLayout> </StackLayout>
@ -45,148 +150,162 @@ import {
Page, Page,
Observable, Observable,
GestureTypes, GestureTypes,
} } from "@nativescript/core";
from "@nativescript/core" import { SnackBar } from "@nativescript-community/ui-material-snackbar";
import {
SnackBar
} from '@nativescript-community/ui-material-snackbar';
const snackbar = new SnackBar(); const snackbar = new SnackBar();
import { import { mapState, mapActions } from "vuex";
mapState, import ViewRecipe from "./ViewRecipe.vue";
mapActions import ActionDialogWithSearch from "./modal/ActionDialogWithSearch.vue";
} import ConfirmDialog from "./modal/ConfirmDialog.vue";
from "vuex"
import ViewRecipe from "./ViewRecipe.vue"
import ActionDialogWithSearch from "./modal/ActionDialogWithSearch.vue"
import ConfirmDialog from "./modal/ConfirmDialog.vue"
export default { export default {
data() { data() {
return { return {
appTheme: "Light", appTheme: "Light",
mealTimes: ["breakfast", "lunch", "dinner", "snacks"], mealTimes: ["breakfast", "lunch", "dinner", "snacks"],
dNames: [ 'SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT' ], dNames: ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"],
year: 2021, year: 2021,
mNames: [ "January", "February", "March", "April", "May", "June", mNames: [
"July", "August", "September", "October", "November", "December" "January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
], ],
month: 0, month: 0,
today: null, today: null,
edit: false, edit: false,
} };
}, },
computed: { computed: {
...mapState(["icon", "recipes", "mealPlans"]), ...mapState(["icon", "recipes", "mealPlans"]),
todaysTime() { todaysTime() {
return new Date( this.year, this.month, this.today, 0 ).getTime() return new Date(this.year, this.month, this.today, 0).getTime();
}, },
getRecipes() { getRecipes() {
if (this.mealPlans.length) { if (this.mealPlans.length) {
return this.mealPlans.reduce((acc, e) => { return this.mealPlans.reduce((acc, e) => {
if (e.date == this.todaysTime) { if (e.date == this.todaysTime) {
acc[ e.type ] = [ ...( acc[ e.type ] || [] ), e.title ] acc[e.type] = [...(acc[e.type] || []), e.title];
} }
return acc return acc;
}, {} ) }, {});
} else return 0 } else return 0;
}, },
getCal() { getCal() {
let y = this.year let y = this.year;
let m = this.month let m = this.month;
let t = this.today let t = this.today;
let d = new Date( y, m, t ) let d = new Date(y, m, t);
let ds = new Date( y, m + 1, 0 ).getDate() let ds = new Date(y, m + 1, 0).getDate();
let fd = new Date( y, m, 1 ).getDay() let fd = new Date(y, m, 1).getDay();
let days = new Array( fd ).fill( 0 ) let days = new Array(fd).fill(0);
for (let i = 1; i <= ds; i++) { for (let i = 1; i <= ds; i++) {
days.push( i ) days.push(i);
} }
return days; return days;
}, },
}, },
methods: { methods: {
...mapActions( [ "setCurrentComponentAction", "addMealPlanAction", "deleteMealPlanAction", ] ), ...mapActions([
"setCurrentComponentAction",
"addMealPlanAction",
"deleteMealPlanAction",
]),
onPageLoad(args) { onPageLoad(args) {
const page = args.object; const page = args.object;
page.bindingContext = new Observable(); page.bindingContext = new Observable();
this.setCurrentComponentAction( "MealPlanner" ) this.setCurrentComponentAction("MealPlanner");
if ( !this.today || this.today === new Date().getDate() ) this.goToToday() if (!this.today || this.today === new Date().getDate()) this.goToToday();
}, },
onPageUnload(args) { onPageUnload(args) {
snackbar.dismiss() snackbar.dismiss();
}, },
// HELPERS // HELPERS
getrow(i) { getrow(i) {
return Math.floor(2 + i / 7); return Math.floor(2 + i / 7);
}, },
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();
}, },
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 : `[ ${this.$options.filters.L('resNF')} ]` return recipe ? recipe.title : `[ ${this.$options.filters.L("resNF")} ]`;
}, },
centerLabel(args) { centerLabel(args) {
args.object.android.setGravity( 17 ) args.object.android.setGravity(17);
}, },
// 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,
}, },
} ) });
} }
}, },
// CALENDAR // CALENDAR
prevMonth() { prevMonth() {
if (this.month == 0) { if (this.month == 0) {
this.year-- this.year--;
this.month = 11 this.month = 11;
} else this.month-- } else this.month--;
}, },
nextMonth() { nextMonth() {
if (this.month == 11) { if (this.month == 11) {
this.year++ this.year++;
this.month = 0 this.month = 0;
} else this.month++ } else this.month++;
}, },
goToToday() { goToToday() {
let d = new Date() let d = new Date();
this.year = d.getFullYear() this.year = d.getFullYear();
this.month = d.getMonth() this.month = d.getMonth();
this.today = d.getDate() this.today = d.getDate();
}, },
isToday(date) { isToday(date) {
let d = new Date() let d = new Date();
return this.year == d.getFullYear() && this.month == d.getMonth() && date == d.getDate() return (
this.year == d.getFullYear() &&
this.month == d.getMonth() &&
date == d.getDate()
);
}, },
isActive(date) { isActive(date) {
return this.today == date return this.today == date;
}, },
hasPlans(date) { hasPlans(date) {
let d = new Date( this.year, this.month, date, 0 ).getTime() let d = new Date(this.year, this.month, date, 0).getTime();
return this.mealPlans.filter( e => e.date == d ).length return this.mealPlans.filter((e) => e.date == d).length;
}, },
setToday(date) { setToday(date) {
if ( date ) this.today = date if (date) this.today = date;
}, },
newMealPlan(title, date, type, index) { newMealPlan(title, date, type, index) {
this.addMealPlanAction({ this.addMealPlanAction({
title, title,
date: date ? date : this.todaysTime, date: date ? date : this.todaysTime,
type, type,
index index,
} ) });
}, },
// DATA HANDLERS // DATA HANDLERS
addRecipe(type) { addRecipe(type) {
let filteredRecipes = this.recipes.filter( ( e ) => this.getRecipes[ type ] ? !this.getRecipes[ type ].includes( e.id ) : true ) let filteredRecipes = this.recipes.filter((e) =>
this.getRecipes[type] ? !this.getRecipes[type].includes(e.id) : true
);
this.$showModal(ActionDialogWithSearch, { this.$showModal(ActionDialogWithSearch, {
props: { props: {
title: "selRec", title: "selRec",
@ -194,40 +313,40 @@ export default {
helpIcon: "cal", helpIcon: "cal",
}, },
}).then((title) => { }).then((title) => {
title && this.newMealPlan( title, null, type, null ) title && this.newMealPlan(title, null, type, null);
} ) });
}, },
removeRecipe(title, type) { removeRecipe(title, type) {
let date = this.todaysTime let date = this.todaysTime;
let index = this.mealPlans.findIndex( e => e.title === title && e.type === type && e.date === date ) let index = this.mealPlans.findIndex(
(e) => e.title === title && e.type === type && e.date === date
);
let mealPlan = { let mealPlan = {
title, title,
date, date,
type, type,
index index,
};
this.deleteMealPlanAction(mealPlan);
this.undoRemove(`${this.$options.filters.L("recRm")}`).then((res) => {
if (res.command === "action") {
this.newMealPlan(title, date, type, index);
} }
this.deleteMealPlanAction( mealPlan ) });
this.undoRemove( `${this.$options.filters.L('recRm')}` ).then( res => {
if ( res.command === 'action' ) {
this.newMealPlan( title, date, type, index )
}
} )
}, },
undoRemove(message) { undoRemove(message) {
return snackbar return snackbar.action({
.action( {
message, message,
textColor: this.appTheme == "Light" ? "#fff" : "#292929", textColor: this.appTheme == "Light" ? "#fff" : "#292929",
actionTextColor: '#ff5200', actionTextColor: "#ff5200",
backgroundColor: this.appTheme == "Light" ? "#292929" : "#fff", backgroundColor: this.appTheme == "Light" ? "#292929" : "#fff",
actionText: 'Undo', actionText: "Undo",
hideDelay: 5000 hideDelay: 5000,
} ) });
}, },
}, },
created() { created() {
this.appTheme = ApplicationSettings.getString( "appTheme", "Light" ) this.appTheme = ApplicationSettings.getString("appTheme", "Light");
}, },
} };
</script> </script>

View file

@ -2,24 +2,43 @@
<Page @loaded="onPageLoad"> <Page @loaded="onPageLoad">
<ActionBar androidElevation="1"> <ActionBar androidElevation="1">
<GridLayout rows="*" columns="auto, *"> <GridLayout rows="*" columns="auto, *">
<MDButton class="er left" variant="text" :text="icon.back" automationText="Back" @tap="$navigateBack()" col="0" /> <MDButton
class="er left"
variant="text"
:text="icon.back"
automationText="Back"
@tap="$navigateBack()"
col="0"
/>
<Label class="title orkm" :text="'Settings' | L" col="1" /> <Label class="title orkm" :text="'Settings' | L" col="1" />
</GridLayout> </GridLayout>
</ActionBar> </ActionBar>
<ScrollView> <ScrollView>
<StackLayout class="main-container"> <StackLayout class="main-container">
<Label :text="'intf' | L" class="group-header orkm" /> <Label :text="'intf' | L" class="group-header orkm" />
<GridLayout columns="auto, *" class="option"> <GridLayout
<MDRipple colSpan="2" @tap="selectAppLanguage" /> columns="auto, *"
<Label col="0" verticalAlignment="center" class="er" :text="icon.lang" /> class="option mdr"
@tap="selectAppLanguage"
>
<Label
col="0"
verticalAlignment="center"
class="er"
:text="icon.lang"
/>
<StackLayout col="1"> <StackLayout col="1">
<Label :text="'lang' | L" /> <Label :text="'lang' | L" />
<Label :text="appLanguage" class="info" /> <Label :text="appLanguage" class="info" />
</StackLayout> </StackLayout>
</GridLayout> </GridLayout>
<GridLayout columns="auto, *" class="option"> <GridLayout columns="auto, *" class="option mdr" @tap="selectThemes">
<MDRipple colSpan="2" @tap="selectThemes" /> <Label
<Label col="0" verticalAlignment="center" class="er" :text="icon.theme" /> col="0"
verticalAlignment="center"
class="er"
:text="icon.theme"
/>
<StackLayout col="1"> <StackLayout col="1">
<Label :text="'Theme' | L" /> <Label :text="'Theme' | L" />
<Label :text="`${appTheme}` | L" class="info" /> <Label :text="`${appTheme}` | L" class="info" />
@ -28,29 +47,47 @@
<StackLayout class="hr m-10"></StackLayout> <StackLayout class="hr m-10"></StackLayout>
<Label :text="'opts' | L" class="group-header orkm" /> <Label :text="'opts' | L" class="group-header orkm" />
<GridLayout columns="auto, *, auto" class="option"> <GridLayout columns="auto, *, auto" class="option">
<Label col="0" verticalAlignment="center" class="er" :text="icon.shuf" /> <Label
col="0"
verticalAlignment="center"
class="er"
:text="icon.shuf"
/>
<StackLayout col="1"> <StackLayout col="1">
<Label :text="'sVw' | L" textWrap="true" /> <Label :text="'sVw' | L" textWrap="true" />
<Label :text="`sVwInfo` | L" class="info" textWrap="true" /> <Label :text="`sVwInfo` | L" class="info" textWrap="true" />
</StackLayout> </StackLayout>
<Switch :color="shakeEnabled ? '#ff5200' : '#858585'" verticalAlignment="center" col="2" :checked="shakeEnabled" @checkedChange="toggleShake" /> <Switch
:color="shakeEnabled ? '#ff5200' : '#858585'"
verticalAlignment="center"
col="2"
:checked="shakeEnabled"
@checkedChange="toggleShake"
/>
</GridLayout> </GridLayout>
<StackLayout class="hr m-10"></StackLayout> <StackLayout class="hr m-10"></StackLayout>
<Label :text="'db' | L" class="group-header orkm" /> <Label :text="'db' | L" class="group-header orkm" />
<GridLayout columns="auto, *" class="option"> <GridLayout columns="auto, *" class="option mdr" @tap="exportCheck">
<MDRipple colSpan="2" @tap="exportCheck" />
<Label col="0" class="er" :text="icon.exp" /> <Label col="0" class="er" :text="icon.exp" />
<StackLayout col="1"> <StackLayout col="1">
<Label :text="'expBu' | L" textWrap="true" /> <Label :text="'expBu' | L" textWrap="true" />
<Label v-if="!backupInProgress" :text="'buInfo' | L" class="info" textWrap="true" /> <Label
v-if="!backupInProgress"
:text="'buInfo' | L"
class="info"
textWrap="true"
/>
<GridLayout class="progressContainer" v-else columns="*, 64"> <GridLayout class="progressContainer" v-else columns="*, 64">
<MDProgress col="0" :value="backupProgress" maxValue="100"></MDProgress> <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 mdr" @tap="importCheck">
<MDRipple colSpan="2" @tap="importCheck" />
<Label col="0" class="er" :text="icon.imp" /> <Label col="0" class="er" :text="icon.imp" />
<StackLayout col="1"> <StackLayout col="1">
<Label :text="'impBu' | L" textWrap="true" /> <Label :text="'impBu' | L" textWrap="true" />
@ -59,48 +96,107 @@
</GridLayout> </GridLayout>
<StackLayout class="hr m-10"></StackLayout> <StackLayout class="hr m-10"></StackLayout>
<Label :text="'rest' | L" class="group-header orkm" /> <Label :text="'rest' | L" class="group-header orkm" />
<GridLayout columns="auto, *" class="option"> <GridLayout
<MDRipple colSpan="2" @tap="resetListItems('cuisines')" /> columns="auto, *"
class="option mdr"
@tap="resetListItems('cuisines')"
>
<Label col="0" class="er" :text="icon.reset" /> <Label col="0" class="er" :text="icon.reset" />
<Label col="1" verticalAlignment="center" :text="'restCuiL' | L" textWrap="true" /> <Label
col="1"
verticalAlignment="center"
:text="'restCuiL' | L"
textWrap="true"
/>
</GridLayout> </GridLayout>
<GridLayout columns="auto, *" class="option"> <GridLayout
<MDRipple colSpan="2" @tap="resetListItems('categories')" /> columns="auto, *"
class="option mdr"
@tap="resetListItems('categories')"
>
<Label col="0" class="er" :text="icon.reset" /> <Label col="0" class="er" :text="icon.reset" />
<Label col="1" verticalAlignment="center" :text="'restCatL' | L" textWrap="true" /> <Label
col="1"
verticalAlignment="center"
:text="'restCatL' | L"
textWrap="true"
/>
</GridLayout> </GridLayout>
<GridLayout columns="auto, *" class="option"> <GridLayout
<MDRipple colSpan="2" @tap="resetListItems('yieldUnits')" /> columns="auto, *"
class="option mdr"
@tap="resetListItems('yieldUnits')"
>
<Label col="0" class="er" :text="icon.reset" /> <Label col="0" class="er" :text="icon.reset" />
<Label col="1" verticalAlignment="center" :text="'restYUL' | L" textWrap="true" /> <Label
col="1"
verticalAlignment="center"
:text="'restYUL' | L"
textWrap="true"
/>
</GridLayout> </GridLayout>
<GridLayout columns="auto, *" class="option"> <GridLayout
<MDRipple colSpan="2" @tap="resetListItems('units')" /> columns="auto, *"
class="option mdr"
@tap="resetListItems('units')"
>
<Label col="0" class="er" :text="icon.reset" /> <Label col="0" class="er" :text="icon.reset" />
<Label col="1" verticalAlignment="center" :text="'restUL' | L" textWrap="true" /> <Label
col="1"
verticalAlignment="center"
:text="'restUL' | L"
textWrap="true"
/>
</GridLayout> </GridLayout>
<Label class="group-info" :text="'restInfo' | L" textWrap="true" /> <Label class="group-info" :text="'restInfo' | L" textWrap="true" />
<StackLayout class="hr m-10"></StackLayout> <StackLayout class="hr m-10"></StackLayout>
<Label :text="'help' | L" class="group-header orkm" /> <Label :text="'help' | L" class="group-header orkm" />
<GridLayout columns="auto, *" class="option"> <GridLayout
<MDRipple colSpan="2" @tap="openURL('https://t.me/enrecipes')" /> columns="auto, *"
class="option mdr"
@tap="openURL('https://t.me/enrecipes')"
>
<Label col="0" class="er" :text="icon.tg" /> <Label col="0" class="er" :text="icon.tg" />
<StackLayout col="1"> <StackLayout col="1">
<Label :text="'joinTG' | L" textWrap="true" /> <Label :text="'joinTG' | L" textWrap="true" />
<Label :text="'tgInfo' | L" class="info" textWrap="true" /> <Label :text="'tgInfo' | L" class="info" textWrap="true" />
</StackLayout> </StackLayout>
</GridLayout> </GridLayout>
<GridLayout columns="auto, *" class="option"> <GridLayout
<MDRipple colSpan="2" @tap="openURL('https://github.com/vishnuraghavb/EnRecipes/wiki/User-Guide')" /> columns="auto, *"
class="option mdr"
@tap="
openURL(
'https://github.com/vishnuraghavb/EnRecipes/wiki/User-Guide'
)
"
>
<Label col="0" class="er" :text="icon.help" /> <Label col="0" class="er" :text="icon.help" />
<Label verticalAlignment="center" col="1" :text="'guide' | L" textWrap="true" /> <Label
verticalAlignment="center"
col="1"
:text="'guide' | L"
textWrap="true"
/>
</GridLayout> </GridLayout>
<GridLayout columns="auto, *" class="option"> <GridLayout
<MDRipple colSpan="2" @tap="openURL('https://github.com/vishnuraghavb/EnRecipes/blob/main/PRIVACY.md')" /> columns="auto, *"
class="option mdr"
@tap="
openURL(
'https://github.com/vishnuraghavb/EnRecipes/blob/main/PRIVACY.md'
)
"
>
<Label col="0" class="er" :text="icon.priv" /> <Label col="0" class="er" :text="icon.priv" />
<Label verticalAlignment="center" col="1" :text="'priv' | L" textWrap="true" /> <Label
verticalAlignment="center"
col="1"
:text="'priv' | L"
textWrap="true"
/>
</GridLayout> </GridLayout>
<StackLayout class="hr m-10"></StackLayout> <StackLayout class="hr m-10"></StackLayout>
<Label :text="'About' | L" class="group-header orkm" /> <Label :text="'About' | L" class="group-header orkm" />
@ -112,20 +208,48 @@
<Label :text="getVersion" class="info" textWrap="true" /> <Label :text="getVersion" class="info" textWrap="true" />
</StackLayout> </StackLayout>
</GridLayout> </GridLayout>
<GridLayout columns="auto, *" class="option"> <GridLayout
<MDRipple colSpan="2" @tap="openURL('https://github.com/vishnuraghavb/enrecipes')" /> columns="auto, *"
class="option mdr"
@tap="openURL('https://github.com/vishnuraghavb/enrecipes')"
>
<Label col="0" class="er" :text="icon.gh" /> <Label col="0" class="er" :text="icon.gh" />
<Label verticalAlignment="center" col="1" :text="'gh' | L" textWrap="true" /> <Label
verticalAlignment="center"
col="1"
:text="'gh' | L"
textWrap="true"
/>
</GridLayout> </GridLayout>
<GridLayout columns="auto, *" class="option"> <GridLayout
<MDRipple colSpan="2" @tap="openURL('https://www.vishnuraghav.com/donate')" /> columns="auto, *"
class="option mdr"
@tap="openURL('https://www.vishnuraghav.com/donate')"
>
<Label col="0" class="er" :text="icon.don" /> <Label col="0" class="er" :text="icon.don" />
<Label verticalAlignment="center" col="1" :text="'donate' | L" textWrap="true" /> <Label
verticalAlignment="center"
col="1"
:text="'donate' | L"
textWrap="true"
/>
</GridLayout> </GridLayout>
<GridLayout columns="auto, *" class="option"> <GridLayout
<MDRipple colSpan="2" @tap="openURL('https://hosted.weblate.org/projects/enrecipes/app-translations')" /> columns="auto, *"
class="option mdr"
@tap="
openURL(
'https://hosted.weblate.org/projects/enrecipes/app-translations'
)
"
>
<Label col="0" class="er" :text="icon.trans" /> <Label col="0" class="er" :text="icon.trans" />
<Label verticalAlignment="center" col="1" :text="'trnsl' | L" textWrap="true" /> <Label
verticalAlignment="center"
col="1"
:text="'trnsl' | L"
textWrap="true"
/>
</GridLayout> </GridLayout>
<Label class="group-info" :text="'appInfo' | L" textWrap="true" /> <Label class="group-info" :text="'appInfo' | L" textWrap="true" />
</StackLayout> </StackLayout>
@ -143,30 +267,18 @@ import {
File, File,
Folder, Folder,
Observable, Observable,
Device Device,
} } from "@nativescript/core";
from "@nativescript/core" import * as Permissions from "@nativescript-community/perms";
import * as Permissions from "@nativescript-community/perms" import { Zip } from "@nativescript/zip";
import { import * as Toast from "nativescript-toast";
Zip import * as Filepicker from "nativescript-plugin-filepicker";
} import Theme from "@nativescript/theme";
from "@nativescript/zip" import { localize, overrideLocale } from "@nativescript/localize";
import * as Toast from "nativescript-toast" import { mapState, mapActions } from "vuex";
import * as Filepicker from "nativescript-plugin-filepicker" import ActionDialog from "./modal/ActionDialog.vue";
import Theme from "@nativescript/theme" import ConfirmDialog from "./modal/ConfirmDialog.vue";
import { import * as utils from "~/shared/utils";
localize,
overrideLocale
}
from "@nativescript/localize"
import {
mapState,
mapActions
}
from "vuex"
import ActionDialog from "./modal/ActionDialog.vue"
import ConfirmDialog from "./modal/ConfirmDialog.vue"
import * as utils from "~/shared/utils"
export default { export default {
data() { data() {
return { return {
@ -174,40 +286,62 @@ export default {
appLanguage: "English", appLanguage: "English",
backupProgress: 0, backupProgress: 0,
backupInProgress: false, backupInProgress: false,
} };
}, },
computed: { computed: {
...mapState( [ "icon", "recipes", "cuisines", "categories", "yieldUnits", "units", "mealPlans", "currentComponent", "language", "shakeEnabled", "importSummary" ] ), ...mapState([
"icon",
"recipes",
"cuisines",
"categories",
"yieldUnits",
"units",
"mealPlans",
"currentComponent",
"language",
"shakeEnabled",
"importSummary",
]),
getVersion() { getVersion() {
let ctx = Application.android.context let ctx = Application.android.context;
return ctx.getPackageManager().getPackageInfo( ctx.getPackageName(), 0 ).versionName return ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), 0)
.versionName;
}, },
}, },
methods: { methods: {
...mapActions( [ "setCurrentComponentAction", "importListItemsAction", "importRecipesAction", "importMealPlansAction", "resetListItemsAction", "setShakeAction", "unlinkBrokenImages" ] ), ...mapActions([
"setCurrentComponentAction",
"importListItemsAction",
"importRecipesAction",
"importMealPlansAction",
"resetListItemsAction",
"setShakeAction",
"unlinkBrokenImages",
]),
onPageLoad(args) { onPageLoad(args) {
const page = args.object; const page = args.object;
page.bindingContext = new Observable(); page.bindingContext = new Observable();
this.setCurrentComponentAction( "Settings" ) this.setCurrentComponentAction("Settings");
}, },
// HELPERS // HELPERS
openURL(url) { openURL(url) {
Utils.openUrl( url ) Utils.openUrl(url);
}, },
// LANGUAGE SELECTION // LANGUAGE SELECTION
selectAppLanguage() { selectAppLanguage() {
let languages = this.language.map( e => e.title ) let languages = this.language.map((e) => e.title);
this.$showModal(ActionDialog, { this.$showModal(ActionDialog, {
props: { props: {
title: "lang", title: "lang",
list: [...languages], list: [...languages],
stretch: true, stretch: true,
helpIcon: 'lang', helpIcon: "lang",
}, },
}).then((action) => { }).then((action) => {
if (action && action !== "Cancel" && this.appLanguage !== action) { if (action && action !== "Cancel" && this.appLanguage !== action) {
let currentLocale = Device.language.split( '-' )[ 0 ] let currentLocale = Device.language.split("-")[0];
let locale = this.language.filter( e => e.title === action )[ 0 ].locale let locale = this.language.filter((e) => e.title === action)[0]
.locale;
if (currentLocale !== locale) { if (currentLocale !== locale) {
this.$showModal(ConfirmDialog, { this.$showModal(ConfirmDialog, {
props: { props: {
@ -215,20 +349,20 @@ export default {
description: localize("nLangInfo"), description: localize("nLangInfo"),
cancelButtonText: "cBtn", cancelButtonText: "cBtn",
okButtonText: "rst", okButtonText: "rst",
helpIcon: 'res', helpIcon: "res",
bgColor: '#ff5200', bgColor: "#ff5200",
}, },
}).then((result) => { }).then((result) => {
if (result) { if (result) {
this.appLanguage = action this.appLanguage = action;
ApplicationSettings.setString( "appLanguage", action ) ApplicationSettings.setString("appLanguage", action);
overrideLocale( locale ) overrideLocale(locale);
setTimeout( utils.restartApp, 250 ) setTimeout(utils.restartApp, 250);
} }
} ) });
} }
} }
} ) });
}, },
// THEME SELECTION // THEME SELECTION
selectThemes() { selectThemes() {
@ -237,7 +371,7 @@ export default {
title: "Theme", title: "Theme",
list: ["Light", "Dark"], list: ["Light", "Dark"],
stretch: false, stretch: false,
helpIcon: 'theme', helpIcon: "theme",
}, },
}).then((action) => { }).then((action) => {
if (action && action !== "Cancel" && this.appTheme !== action) { if (action && action !== "Cancel" && this.appTheme !== action) {
@ -247,169 +381,224 @@ export default {
description: localize("nThmInfo"), description: localize("nThmInfo"),
cancelButtonText: "cBtn", cancelButtonText: "cBtn",
okButtonText: "rst", okButtonText: "rst",
helpIcon: 'res', helpIcon: "res",
bgColor: '#ff5200', bgColor: "#ff5200",
}, },
}).then((result) => { }).then((result) => {
if (result) { if (result) {
this.appTheme = action this.appTheme = action;
ApplicationSettings.setString( "appTheme", action ) ApplicationSettings.setString("appTheme", action);
setTimeout( utils.restartApp, 250 ) setTimeout(utils.restartApp, 250);
} }
} ) });
} }
} ) });
}, },
// SHAKE VIEW RANDOM RECIPE // SHAKE VIEW RANDOM RECIPE
toggleShake(args) { toggleShake(args) {
let checked = args.object.checked let checked = args.object.checked;
// let checked = !this.shakeEnabled // let checked = !this.shakeEnabled
ApplicationSettings.setBoolean( 'shakeEnabled', checked ) ApplicationSettings.setBoolean("shakeEnabled", checked);
this.setShakeAction( checked ) this.setShakeAction(checked);
}, },
// EXPORT HANDLERS // EXPORT HANDLERS
exportCheck() { exportCheck() {
if (!this.recipes.length) { if (!this.recipes.length) {
Toast.makeText( localize( "aFBu" ) ).show() Toast.makeText(localize("aFBu")).show();
} else { } else {
this.permissionCheck( this.permissionConfirmation, localize( "reqAcc" ), this.exportBackup ) this.permissionCheck(
this.permissionConfirmation,
localize("reqAcc"),
this.exportBackup
);
} }
}, },
exportBackup() { exportBackup() {
this.exportFiles( "create" ) this.exportFiles("create");
let date = new Date() let date = new Date();
let formattedDate = date.getFullYear() + "-" + ( "0" + ( date.getMonth() + 1 ) ).slice( -2 ) + "-" + ( "0" + date.getDate() ).slice( -2 ) + "_" + ( "0" + date.getHours() ).slice( -2 ) + ( "0" + date.getMinutes() ).slice( -2 ) + ( "0" + date let formattedDate =
.getSeconds() ).slice( -2 ) date.getFullYear() +
const sdDownloadPath = Folder.fromPath( android.os.Environment.getExternalStorageDirectory().getAbsolutePath() ).getFolder( "Download" ).path "-" +
let fromPath = path.join( knownFolders.documents().path, "EnRecipes" ) ("0" + (date.getMonth() + 1)).slice(-2) +
let destPath = path.join( sdDownloadPath, `EnRecipes-Backup_${formattedDate}.zip` ) "-" +
this.backupInProgress = true ("0" + date.getDate()).slice(-2) +
"_" +
("0" + date.getHours()).slice(-2) +
("0" + date.getMinutes()).slice(-2) +
("0" + date.getSeconds()).slice(-2);
const sdDownloadPath = Folder.fromPath(
android.os.Environment.getExternalStorageDirectory().getAbsolutePath()
).getFolder("Download").path;
let fromPath = path.join(knownFolders.documents().path, "EnRecipes");
let destPath = path.join(
sdDownloadPath,
`EnRecipes-Backup_${formattedDate}.zip`
);
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( "Backup file successfully saved to Download folder", "long" ).show() Toast.makeText(
this.exportFiles( "delete" ) "Backup file successfully saved to Download folder",
setTimeout( e => this.backupInProgress = false, 3000 ) "long"
} ) ).show();
this.exportFiles("delete");
setTimeout((e) => (this.backupInProgress = false), 3000);
});
}, },
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 userCuisinesFile, userCategoriesFile, userYieldUnitsFile, userUnitsFile, mealPlansFile let userCuisinesFile,
if ( this.cuisines.length ) userCuisinesFile = File.fromPath( path.join( folder, "userCuisines.json" ) ) userCategoriesFile,
if ( this.categories.length ) userCategoriesFile = File.fromPath( path.join( folder, "userCategories.json" ) ) userYieldUnitsFile,
if ( this.yieldUnits.length ) userYieldUnitsFile = File.fromPath( path.join( folder, "userYieldUnits.json" ) ) userUnitsFile,
if ( this.units.length ) userUnitsFile = File.fromPath( path.join( folder, "userUnits.json" ) ) mealPlansFile;
if ( this.mealPlans.length ) mealPlansFile = File.fromPath( path.join( folder, "mealPlans.json" ) ) if (this.cuisines.length)
userCuisinesFile = File.fromPath(
path.join(folder, "userCuisines.json")
);
if (this.categories.length)
userCategoriesFile = File.fromPath(
path.join(folder, "userCategories.json")
);
if (this.yieldUnits.length)
userYieldUnitsFile = File.fromPath(
path.join(folder, "userYieldUnits.json")
);
if (this.units.length)
userUnitsFile = File.fromPath(path.join(folder, "userUnits.json"));
if (this.mealPlans.length)
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.cuisines.length && this.writeDataToFile( userCuisinesFile, this.cuisines ) this.cuisines.length &&
this.categories.length && this.writeDataToFile( userCategoriesFile, this.categories ) this.writeDataToFile(userCuisinesFile, this.cuisines);
this.yieldUnits.length && this.writeDataToFile( userYieldUnitsFile, this.yieldUnits ) this.categories.length &&
this.units.length && this.writeDataToFile( userUnitsFile, this.units ) this.writeDataToFile(userCategoriesFile, this.categories);
this.mealPlans.length && this.writeDataToFile( mealPlansFile, this.mealPlans ) this.yieldUnits.length &&
break this.writeDataToFile(userYieldUnitsFile, this.yieldUnits);
this.units.length && this.writeDataToFile(userUnitsFile, this.units);
this.mealPlans.length &&
this.writeDataToFile(mealPlansFile, this.mealPlans);
break;
case "delete": case "delete":
EnRecipesFile.remove() EnRecipesFile.remove();
this.cuisines.length && userCuisinesFile.remove() this.cuisines.length && userCuisinesFile.remove();
this.categories.length && userCategoriesFile.remove() this.categories.length && userCategoriesFile.remove();
this.yieldUnits.length && userYieldUnitsFile.remove() this.yieldUnits.length && userYieldUnitsFile.remove();
this.units.length && userUnitsFile.remove() this.units.length && userUnitsFile.remove();
this.mealPlans.length && mealPlansFile.remove() this.mealPlans.length && mealPlansFile.remove();
break break;
default: 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.permissionConfirmation, localize( "reqAcc" ), this.openFilePicker ) this.permissionCheck(
this.permissionConfirmation,
localize("reqAcc"),
this.openFilePicker
);
}, },
openFilePicker() { openFilePicker() {
Filepicker.create({ Filepicker.create({
mode: "single", mode: "single",
extensions: ["zip"], extensions: ["zip"],
} ).present().then( ( selection ) => {
Toast.makeText( localize( "vrfy" ) + '...' ).show()
let zipPath = selection[ 0 ]
this.validateZipContent( zipPath )
}) })
.present()
.then((selection) => {
Toast.makeText(localize("vrfy") + "...").show();
let zipPath = selection[0];
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 "userCuisinesDB": case "userCuisinesDB":
this.importListItemsAction({ this.importListItemsAction({
data, data,
listName: "cuisines", listName: "cuisines",
} ) });
break break;
case "userCategoriesDB": case "userCategoriesDB":
this.importListItemsAction({ this.importListItemsAction({
data, data,
listName: "categories", listName: "categories",
} ) });
break break;
case "userYieldUnitsDB": case "userYieldUnitsDB":
this.importListItemsAction({ this.importListItemsAction({
data, data,
listName: "yieldUnits", listName: "yieldUnits",
} ) });
break break;
case "userUnitsDB": case "userUnitsDB":
this.importListItemsAction({ this.importListItemsAction({
data, data,
listName: "units", listName: "units",
} ) });
break break;
case "mealPlansDB": case "mealPlansDB":
this.importMealPlansAction( data ) this.importMealPlansAction(data);
break break;
default: default:
break break;
} }
}, },
hasValidJSON(data) { hasValidJSON(data) {
try { try {
JSON.parse( data ) && Array.isArray( JSON.parse( data ) ) JSON.parse(data) && Array.isArray(JSON.parse(data));
} catch (e) { } catch (e) {
return false; return false;
} }
return true; return true;
}, },
isFileDataValid(file) { isFileDataValid(file) {
const files = file.filter( e => File.exists( e.path ) ) const files = file.filter((e) => File.exists(e.path));
if (files.length) { if (files.length) {
let isValid = files.map( e => false ) let isValid = files.map((e) => false);
files.forEach((file, i) => { files.forEach((file, i) => {
File.fromPath( file.path ).readText().then( ( data ) => { File.fromPath(file.path)
isValid[ i ] = this.hasValidJSON( data ) .readText()
.then((data) => {
isValid[i] = this.hasValidJSON(data);
if (!isValid[i]) { if (!isValid[i]) {
this.failedImport( `${localize("buMod")}\n\n${localize("invFile")}: ${file.file}` ) this.failedImport(
`${localize("buMod")}\n\n${localize("invFile")}: ${file.file}`
);
return 0; return 0;
} }
if ( isValid.every( e => e === true ) ) { if (isValid.every((e) => e === true)) {
files.forEach((file, i) => { files.forEach((file, i) => {
File.fromPath( file.path ).readText().then( ( data ) => { File.fromPath(file.path)
this.importDataToDB( JSON.parse( data ), file.db, file.zipPath ) .readText()
} ) .then((data) => {
} ) this.importDataToDB(
JSON.parse(data),
file.db,
file.zipPath
);
});
});
} }
} ) });
} ) });
} else { } else {
this.failedImport( localize( "buEmp" ) ) this.failedImport(localize("buEmp"));
} }
}, },
failedImport(description) { failedImport(description) {
@ -418,94 +607,99 @@ export default {
title: "impFail", title: "impFail",
description, description,
okButtonText: "OK", okButtonText: "OK",
helpIcon: 'alert', helpIcon: "alert",
bgColor: '#c92a2a', bgColor: "#c92a2a",
}, },
} ) });
}, },
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 userCuisinesFilePath = cacheFolderPath + "/userCuisines.json" const userCuisinesFilePath = cacheFolderPath + "/userCuisines.json";
const userCategoriesFilePath = cacheFolderPath + "/userCategories.json" const userCategoriesFilePath = cacheFolderPath + "/userCategories.json";
const userYieldUnitsFilePath = cacheFolderPath + "/userYieldUnits.json" const userYieldUnitsFilePath = cacheFolderPath + "/userYieldUnits.json";
const userUnitsFilePath = cacheFolderPath + "/userUnits.json" const userUnitsFilePath = cacheFolderPath + "/userUnits.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",
file: "recipes.json" file: "recipes.json",
}, { },
{
zipPath, zipPath,
path: userCuisinesFilePath, path: userCuisinesFilePath,
db: "userCuisinesDB", db: "userCuisinesDB",
file: "userCuisines.json" file: "userCuisines.json",
}, { },
{
zipPath, zipPath,
path: userCategoriesFilePath, path: userCategoriesFilePath,
db: "userCategoriesDB", db: "userCategoriesDB",
file: "userCategories.json" file: "userCategories.json",
}, { },
{
zipPath, zipPath,
path: userYieldUnitsFilePath, path: userYieldUnitsFilePath,
db: "userYieldUnitsDB", db: "userYieldUnitsDB",
file: "userYieldUnits.json" file: "userYieldUnits.json",
}, { },
{
zipPath, zipPath,
path: userUnitsFilePath, path: userUnitsFilePath,
db: "userUnitsDB", db: "userUnitsDB",
file: "userUnits.json" file: "userUnits.json",
}, { },
{
zipPath, zipPath,
path: mealPlansFilePath, path: mealPlansFilePath,
db: "mealPlansDB", db: "mealPlansDB",
file: "mealPlans.json" file: "mealPlans.json",
}, ] ) },
]);
} else { } else {
Folder.fromPath( extractedFolderPath ).remove() Folder.fromPath(extractedFolderPath).remove();
this.failedImport( localize( "buInc" ) ) this.failedImport(localize("buInc"));
} }
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) => {
this.showImportSummary() this.showImportSummary();
this.unlinkBrokenImages() this.unlinkBrokenImages();
} ) });
}, },
showImportSummary() { showImportSummary() {
let { let { found, imported, updated } = this.importSummary;
found, let exists = Math.abs(found - imported - updated) + updated;
imported, let importedNote = `\n${imported} ${localize("recI")}`;
updated let existsNote = `\n${exists} ${localize("recE")}`;
} = this.importSummary let updatedNote = `\n${updated} ${localize("recU")}`;
let exists = Math.abs( found - imported - updated ) + updated
let importedNote = `\n${imported} ${localize('recI')}`
let existsNote = `\n${exists} ${localize('recE')}`
let updatedNote = `\n${updated} ${localize('recU')}`
this.$showModal(ConfirmDialog, { this.$showModal(ConfirmDialog, {
props: { props: {
title: "impSuc", title: "impSuc",
description: `${found} ${localize('recF')}${ importedNote}${existsNote}${updatedNote}`, description: `${found} ${localize(
"recF"
)}${importedNote}${existsNote}${updatedNote}`,
okButtonText: "OK", okButtonText: "OK",
helpIcon: 'succ', helpIcon: "succ",
bgColor: '#69db7c', bgColor: "#69db7c",
}, },
} ) });
}, },
// PERMISSIONS HANDLER // PERMISSIONS HANDLER
permissionCheck(confirmation, description, action) { permissionCheck(confirmation, description, action) {
@ -513,22 +707,23 @@ export default {
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" ) ApplicationSettings.setBoolean( "storagePermissionAsked", true ) if (status !== "denied")
else Toast.makeText( localize( "dend" ) ).show() ApplicationSettings.setBoolean("storagePermissionAsked", true);
} ) else Toast.makeText(localize("dend")).show();
});
} }
} ) });
} else { } else {
Permissions.check("photo").then((res) => { Permissions.check("photo").then((res) => {
let status = res[ Object.keys( res )[ 0 ] ] let status = res[Object.keys(res)[0]];
if (status !== "authorized") { if (status !== "authorized") {
confirmation(description).then((e) => { confirmation(description).then((e) => {
e && utils.openAppSettingsPage() e && utils.openAppSettingsPage();
} ) });
} else action() } else action();
} ) });
} }
}, },
permissionConfirmation(description) { permissionConfirmation(description) {
@ -538,21 +733,23 @@ export default {
description, description,
cancelButtonText: "nNBtn", cancelButtonText: "nNBtn",
okButtonText: "conBtn", okButtonText: "conBtn",
helpIcon: 'folder', helpIcon: "folder",
bgColor: '#ff5200', bgColor: "#ff5200",
}, },
} ) });
}, },
// RESET // RESET
resetListItems(listName) { resetListItems(listName) {
this.resetListItemsAction( listName ) this.resetListItemsAction(listName);
Toast.makeText( localize( "restDone" ) ).show() Toast.makeText(localize("restDone")).show();
} },
}, },
mounted() { mounted() {
this.appTheme = ApplicationSettings.getString( "appTheme", "Light" ) this.appTheme = ApplicationSettings.getString("appTheme", "Light");
this.appLanguage = ApplicationSettings.getString( "appLanguage", localize( "sysDef" ) ) this.appLanguage = ApplicationSettings.getString(
"appLanguage",
localize("sysDef")
);
}, },
} };
</script> </script>

File diff suppressed because it is too large Load diff

View file

@ -1,115 +1,144 @@
<template> <template>
<Page> <Page>
<GridLayout columns="*" :rows="`auto, auto, ${stretch? '*':'auto'}, auto`" class="dialogContainer" :class="appTheme"> <GridLayout
<Label row="0" class="er dialogIcon" backgroundColor="#858585" :color="iconColor" :text="icon[helpIcon]" /> columns="*"
:rows="`auto, auto, ${stretch ? '*' : 'auto'}, auto`"
class="dialogContainer"
:class="appTheme"
>
<Label
row="0"
class="er dialogIcon"
backgroundColor="#858585"
:color="iconColor"
:text="icon[helpIcon]"
/>
<Label row="1" class="dialogTitle orkm" :text="`${title}` | L" /> <Label row="1" class="dialogTitle orkm" :text="`${title}` | L" />
<ScrollView row="2" width="100%"> <ScrollView row="2" width="100%">
<StackLayout> <StackLayout>
<MDButton v-for="(item, index) in newList" :key="index" class="actionItem" :class="{'orkm':title==='srt' && sortType=== item}" :color="title==='srt' && sortType=== item ? '#ff5200':''" variant="text" :rippleColor="rippleColor" <MDButton
:text="`${localized(item)}${title==='srt' && sortType=== item ? '*':''}`" @loaded="centerLabel" @tap="tapAction(item)" @longPress="removeItem(index)" /> v-for="(item, index) in newList"
:key="index"
class="actionItem"
:class="{ orkm: title === 'srt' && sortType === item }"
:color="title === 'srt' && sortType === item ? '#ff5200' : ''"
variant="text"
:text="`${localized(item)}${
title === 'srt' && sortType === item ? '*' : ''
}`"
@loaded="centerLabel"
@tap="tapAction(item)"
@longPress="removeItem(index)"
/>
</StackLayout> </StackLayout>
</ScrollView> </ScrollView>
<GridLayout row="3" rows="auto" columns="auto, *, auto" class="actionsContainer"> <GridLayout
<MDButton :rippleColor="rippleColor" variant="text" v-if="action" col="0" class="action orkm pull-left" :text="`${action}` | L" @tap="$modal.close(action)" /> row="3"
<MDButton :rippleColor="rippleColor" variant="text" col="2" class="action orkm pull-right" :text="'cBtn' | L" @tap="$modal.close(false)" /> rows="auto"
columns="auto, *, auto"
class="actionsContainer"
>
<MDButton
variant="text"
v-if="action"
col="0"
class="action orkm pull-left"
:text="`${action}` | L"
@tap="$modal.close(action)"
/>
<MDButton
variant="text"
col="2"
class="action orkm pull-right"
:text="'cBtn' | L"
@tap="$modal.close(false)"
/>
</GridLayout> </GridLayout>
</GridLayout> </GridLayout>
</Page> </Page>
</template> </template>
<script> <script>
import { import { Application, Color } from "@nativescript/core";
Application, import * as Toast from "nativescript-toast";
Color import { localize } from "@nativescript/localize";
} from "@nativescript/core" import { mapState, mapActions } from "vuex";
import * as Toast from "nativescript-toast" import ConfirmDialog from "./ConfirmDialog.vue";
import {
localize
}
from "@nativescript/localize"
import {
mapState,
mapActions
}
from "vuex"
import ConfirmDialog from "./ConfirmDialog.vue"
export default { export default {
props: ["title", "list", "stretch", "action", "helpIcon"], props: ["title", "list", "stretch", "action", "helpIcon"],
data() { data() {
return { return {
newList: this.list, newList: this.list,
} };
}, },
computed: { computed: {
...mapState( [ "sortType", 'icon' ] ), ...mapState(["sortType", "icon"]),
appTheme() { appTheme() {
return Application.systemAppearance() return Application.systemAppearance();
}, },
isLightMode() { isLightMode() {
return this.appTheme == "light" return this.appTheme == "light";
},
rippleColor() {
return "rgba(133,133,133,0.2)"
}, },
iconColor() { iconColor() {
return this.isLightMode ? "#f0f0f0" : "#1A1A1A" return this.isLightMode ? "#f0f0f0" : "#1A1A1A";
}, },
}, },
methods: { methods: {
...mapActions(["removeListItemAction"]), ...mapActions(["removeListItemAction"]),
localized(item) { localized(item) {
if ( this.title !== 'lang' ) if (this.title !== "lang") return localize(item);
return localize( item ) else return item;
else
return item
}, },
tapAction(item) { tapAction(item) {
this.$modal.close( item ) this.$modal.close(item);
}, },
centerLabel(args) { centerLabel(args) {
args.object.android.setGravity( 16 ) args.object.android.setGravity(16);
}, },
deletionConfirmation(type, description) { deletionConfirmation(type, description) {
return this.$showModal(ConfirmDialog, { return this.$showModal(ConfirmDialog, {
props: { props: {
title: 'conf', title: "conf",
description, description,
cancelButtonText: "cBtn", cancelButtonText: "cBtn",
okButtonText: "rBtn", okButtonText: "rBtn",
helpIcon: 'err', helpIcon: "err",
bgColor: '#c92a2a', bgColor: "#c92a2a",
}, },
} ) });
}, },
removeItem(index) { removeItem(index) {
let item = this.newList[ index ] let item = this.newList[index];
let vm = this let vm = this;
function removeListItem(type, listName, desc) { function removeListItem(type, listName, desc) {
vm.deletionConfirmation( type, `${localize(desc)} "${localize(item)}"\n\n${localize('rmLIInfo')}` ).then( action => { vm.deletionConfirmation(
type,
`${localize(desc)} "${localize(item)}"\n\n${localize("rmLIInfo")}`
).then((action) => {
if (action != null && action) if (action != null && action)
vm.removeListItemAction({ vm.removeListItemAction({
item, item,
listName listName,
} ) });
} ) });
} }
switch (this.title) { switch (this.title) {
case "cui": case "cui":
removeListItem( 'cuisine', "cuisines", "rmCuiInfo" ) removeListItem("cuisine", "cuisines", "rmCuiInfo");
break; break;
case "cat": case "cat":
removeListItem( "category", "categories", "rmCatInfo" ) removeListItem("category", "categories", "rmCatInfo");
break; break;
case "yieldU": case "yieldU":
removeListItem( "yield unit", "yieldUnits", "rmYUInfo" ) removeListItem("yield unit", "yieldUnits", "rmYUInfo");
break; break;
case "Unit": case "Unit":
removeListItem( "unit", "units", "rmUInfo" ) removeListItem("unit", "units", "rmUInfo");
break; break;
default: default:
} }
}
}, },
} },
};
</script> </script>

View file

@ -1,81 +1,139 @@
<template> <template>
<Page> <Page>
<GridLayout columns="*" rows="auto, auto, auto, *, auto" class="dialogContainer" :class="appTheme"> <GridLayout
<Label row="0" class="er dialogIcon" backgroundColor="#858585" :color="iconColor" :text="icon[helpIcon]" /> columns="*"
<Label row="1" class="dialogTitle orkm" :text="`${title}` | L" textWrap='true' /> rows="auto, auto, auto, *, auto"
<StackLayout row="2" v-if="filteredRecipes.length || searchQuery" padding="0 24 24"> class="dialogContainer"
:class="appTheme"
>
<Label
row="0"
class="er dialogIcon"
backgroundColor="#858585"
:color="iconColor"
:text="icon[helpIcon]"
/>
<Label
row="1"
class="dialogTitle orkm"
:text="`${title}` | L"
textWrap="true"
/>
<StackLayout
row="2"
v-if="filteredRecipes.length || searchQuery"
padding="0 24 24"
>
<TextField :hint="'Search' | L" v-model="searchQuery" /> <TextField :hint="'Search' | L" v-model="searchQuery" />
</StackLayout> </StackLayout>
<ScrollView row="3" width="100%" :height="height ? height : ''"> <ScrollView row="3" width="100%" :height="height ? height : ''">
<StackLayout> <StackLayout>
<MDButton v-for="(recipe, index) in filteredRecipes" :key="index" class="actionItem" variant="text" :rippleColor="rippleColor" :text="recipe.title" @loaded="centerLabel" @tap="tapAction(recipe)" /> <MDButton
<Label padding="24" lineHeight="6" v-if="!filteredRecipes.length && !searchQuery" :text="'recListEmp' | L" textAlignment="center" textWrap="true" /> v-for="(recipe, index) in filteredRecipes"
<Label padding="24" lineHeight="6" v-if="!filteredRecipes.length && searchQuery" :text="'noRecs' | L" textAlignment="center" textWrap="true" /> :key="index"
class="actionItem"
variant="text"
:text="recipe.title"
@loaded="centerLabel"
@tap="tapAction(recipe)"
/>
<Label
padding="24"
lineHeight="6"
v-if="!filteredRecipes.length && !searchQuery"
:text="'recListEmp' | L"
textAlignment="center"
textWrap="true"
/>
<Label
padding="24"
lineHeight="6"
v-if="!filteredRecipes.length && searchQuery"
:text="'noRecs' | L"
textAlignment="center"
textWrap="true"
/>
</StackLayout> </StackLayout>
</ScrollView> </ScrollView>
<GridLayout row="4" rows="auto" columns="auto, *, auto" class="actionsContainer"> <GridLayout
<MDButton :rippleColor="rippleColor" variant="text" v-if="action" col="0" class="action orkm pull-left" :text="`${action}` | L" @tap="$modal.close(action)" /> row="4"
<MDButton :rippleColor="rippleColor" variant="text" col="2" class="action orkm pull-right" :text="'CANCEL' | L" @tap="$modal.close(false)" /> rows="auto"
columns="auto, *, auto"
class="actionsContainer"
>
<MDButton
variant="text"
v-if="action"
col="0"
class="action orkm pull-left"
:text="`${action}` | L"
@tap="$modal.close(action)"
/>
<MDButton
variant="text"
col="2"
class="action orkm pull-right"
:text="'CANCEL' | L"
@tap="$modal.close(false)"
/>
</GridLayout> </GridLayout>
</GridLayout> </GridLayout>
</Page> </Page>
</template> </template>
<script> <script>
import { import { Application } from "@nativescript/core";
Application import { mapState } from "vuex";
}
from "@nativescript/core"
import {
mapState
}
from "vuex"
export default { export default {
props: ["title", "recipes", "height", "action", "helpIcon"], props: ["title", "recipes", "height", "action", "helpIcon"],
data() { data() {
return { return {
searchQuery: "", searchQuery: "",
} };
}, },
computed: { computed: {
...mapState( [ 'icon' ] ), ...mapState(["icon"]),
appTheme() { appTheme() {
return Application.systemAppearance() return Application.systemAppearance();
}, },
isLightMode() { isLightMode() {
return this.appTheme == "light" return this.appTheme == "light";
},
rippleColor() {
return "rgba(133,133,133,0.2)"
}, },
iconColor() { iconColor() {
return this.isLightMode ? "#f0f0f0" : "#1A1A1A" return this.isLightMode ? "#f0f0f0" : "#1A1A1A";
}, },
filteredRecipes() { filteredRecipes() {
return this.recipes.map( ( e, i ) => { return this.recipes
.map((e, i) => {
return { return {
id: e.id, id: e.id,
title: e.title, title: e.title,
cuisine: e.cuisine, cuisine: e.cuisine,
category: e.category, category: e.category,
tags: e.tags.map( e => e.toLowerCase() ).join(), tags: e.tags.map((e) => e.toLowerCase()).join(),
ingredients: e.ingredients.map( e => e.item.toLowerCase() ).join(), ingredients: e.ingredients.map((e) => e.item.toLowerCase()).join(),
} };
} ).filter( ( e ) => this.recipeFilter( e ) ) })
.filter((e) => this.recipeFilter(e));
}, },
}, },
methods: { methods: {
tapAction(recipe) { tapAction(recipe) {
this.$modal.close( recipe.id ) this.$modal.close(recipe.id);
}, },
centerLabel(args) { centerLabel(args) {
args.object.android.setGravity( 16 ) args.object.android.setGravity(16);
}, },
recipeFilter(e) { recipeFilter(e) {
let searchQuery = this.searchQuery.toLowerCase() let searchQuery = this.searchQuery.toLowerCase();
return e.title.includes( searchQuery ) || e.cuisine.includes( searchQuery ) || e.category.includes( searchQuery ) || e.tags.includes( searchQuery ) || e.ingredients.includes( searchQuery ) return (
e.title.includes(searchQuery) ||
e.cuisine.includes(searchQuery) ||
e.category.includes(searchQuery) ||
e.tags.includes(searchQuery) ||
e.ingredients.includes(searchQuery)
);
}, },
}, },
} };
</script> </script>

View file

@ -1,42 +1,63 @@
<template> <template>
<Page> <Page>
<StackLayout class="dialogContainer" :class="appTheme"> <StackLayout class="dialogContainer" :class="appTheme">
<Label class="er dialogIcon" :backgroundColor="bgColor" :color="iconColor" :text="icon[helpIcon]" /> <Label
class="er dialogIcon"
:backgroundColor="bgColor"
:color="iconColor"
:text="icon[helpIcon]"
/>
<Label class="dialogTitle orkm" :text="`${title}` | L" textWrap="true" /> <Label class="dialogTitle orkm" :text="`${title}` | L" textWrap="true" />
<Label v-if="description" class="dialogDescription" :text="description" textWrap="true" /> <Label
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 v-if="cancelButtonText" :rippleColor="rippleColor" variant="text" col="1" class="action orkm" :text="`${cancelButtonText}` | L" @tap="$modal.close(false)" /> <MDButton
<MDButton :rippleColor="rippleColor" variant="text" col="2" class="action orkm" :text="`${okButtonText}` | L" @tap="$modal.close(true)" /> v-if="cancelButtonText"
variant="text"
col="1"
class="action orkm"
:text="`${cancelButtonText}` | L"
@tap="$modal.close(false)"
/>
<MDButton
variant="text"
col="2"
class="action orkm"
:text="`${okButtonText}` | L"
@tap="$modal.close(true)"
/>
</GridLayout> </GridLayout>
</StackLayout> </StackLayout>
</Page> </Page>
</template> </template>
<script> <script>
import { import { Application } from "@nativescript/core";
Application import { mapState } from "vuex";
}
from "@nativescript/core"
import {
mapState
}
from "vuex"
export default { export default {
props: [ "title", "description", "cancelButtonText", "okButtonText", "helpIcon", "bgColor" ], props: [
"title",
"description",
"cancelButtonText",
"okButtonText",
"helpIcon",
"bgColor",
],
computed: { computed: {
...mapState(["icon"]), ...mapState(["icon"]),
appTheme() { appTheme() {
return Application.systemAppearance() return Application.systemAppearance();
}, },
isLightMode() { isLightMode() {
return this.appTheme == "light" return this.appTheme == "light";
},
rippleColor() {
return "rgba(133,133,133,0.2)"
}, },
iconColor() { iconColor() {
return this.isLightMode ? "#f0f0f0" : "#1A1A1A" return this.isLightMode ? "#f0f0f0" : "#1A1A1A";
}, },
}, },
} };
</script> </script>

View file

@ -1,33 +1,55 @@
<template> <template>
<Page> <Page>
<StackLayout class="dialogContainer" :class="appTheme"> <StackLayout class="dialogContainer" :class="appTheme">
<Label class="er dialogIcon" backgroundColor="#858585" :color="iconColor" :text="icon.time" /> <Label
class="er dialogIcon"
backgroundColor="#858585"
:color="iconColor"
:text="icon.time"
/>
<Label class="dialogTitle orkm" :text="`${title}` | L" /> <Label class="dialogTitle orkm" :text="`${title}` | L" />
<StackLayout class="dialogListPicker" orientation="horizontal" horizontalAlignment="center"> <StackLayout
<ListPicker ref="hrPicker" :items="hrsList" :selectedIndex="hrIndex" @selectedIndexChange="setHrs"></ListPicker> class="dialogListPicker"
<ListPicker ref="minPicker" :items="minsList" :selectedIndex="minIndex" @selectedIndexChange="setMins"></ListPicker> orientation="horizontal"
horizontalAlignment="center"
>
<ListPicker
ref="hrPicker"
:items="hrsList"
:selectedIndex="hrIndex"
@selectedIndexChange="setHrs"
></ListPicker>
<ListPicker
ref="minPicker"
:items="minsList"
:selectedIndex="minIndex"
@selectedIndexChange="setMins"
></ListPicker>
</StackLayout> </StackLayout>
<GridLayout rows="auto" columns="*, auto, auto" class="actionsContainer"> <GridLayout rows="auto" columns="*, auto, auto" class="actionsContainer">
<MDButton :rippleColor="rippleColor" variant="text" col="1" class="action orkm" :text="'cBtn' | L" @tap="$modal.close(false)" /> <MDButton
<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="'cBtn' | L"
@tap="$modal.close(false)"
/>
<MDButton
variant="text"
col="2"
class="action orkm"
:text="`${action}` | L"
@tap="$modal.close(selectedTime)"
/>
</GridLayout> </GridLayout>
</StackLayout> </StackLayout>
</Page> </Page>
</template> </template>
<script> <script>
import { import { Application } from "@nativescript/core";
Application import { mapState } from "vuex";
} import { localize } from "@nativescript/localize";
from "@nativescript/core"
import {
mapState
}
from "vuex"
import {
localize
}
from "@nativescript/localize"
export default { export default {
props: ["title", "selectedHr", "selectedMin", "action"], props: ["title", "selectedHr", "selectedMin", "action"],
data() { data() {
@ -36,51 +58,53 @@ export default {
mins: [], mins: [],
selectedHrs: "00", selectedHrs: "00",
selectedMins: "00", selectedMins: "00",
} };
}, },
computed: { computed: {
...mapState(["icon"]), ...mapState(["icon"]),
hrsList() { hrsList() {
let h = [ ...Array( 24 ).keys() ] let h = [...Array(24).keys()];
this.hrs = h this.hrs = h;
return h.map( e => `${e} ${localize( 'hr' )}` ) return h.map((e) => `${e} ${localize("hr")}`);
}, },
minsList() { minsList() {
let m = [ ...new Set( [ ...Array( 11 ).keys(), ...Array.from( Array( 12 ), ( _, x ) => x * 5 ) ] ) ] let m = [
this.mins = m ...new Set([
return m.map( e => `${e} ${localize( 'min' )}` ) ...Array(11).keys(),
...Array.from(Array(12), (_, x) => x * 5),
]),
];
this.mins = m;
return m.map((e) => `${e} ${localize("min")}`);
}, },
hrIndex() { hrIndex() {
return this.hrs.indexOf( parseInt( this.selectedHr ) ) return this.hrs.indexOf(parseInt(this.selectedHr));
}, },
minIndex() { minIndex() {
return this.mins.indexOf( parseInt( this.selectedMin ) ) return this.mins.indexOf(parseInt(this.selectedMin));
}, },
appTheme() { appTheme() {
return Application.systemAppearance() return Application.systemAppearance();
}, },
isLightMode() { isLightMode() {
return this.appTheme == "light" return this.appTheme == "light";
},
rippleColor() {
return "rgba(133,133,133,0.2)"
}, },
iconColor() { iconColor() {
return this.isLightMode ? "#f0f0f0" : "#1A1A1A" return this.isLightMode ? "#f0f0f0" : "#1A1A1A";
}, },
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( -2 ) 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( -2 ) this.selectedMins = min.slice(-2);
}, },
}, },
} };
</script> </script>

View file

@ -1,65 +1,75 @@
<template> <template>
<Page> <Page>
<StackLayout class="dialogContainer" :class="appTheme"> <StackLayout class="dialogContainer" :class="appTheme">
<Label class="er dialogIcon" backgroundColor="#858585" :color="iconColor" :text="icon[helpIcon]" /> <Label
<Label class="dialogTitle orkm" :text="`${title}` | L" textWrap='true' /> class="er dialogIcon"
backgroundColor="#858585"
:color="iconColor"
:text="icon[helpIcon]"
/>
<Label class="dialogTitle orkm" :text="`${title}` | L" textWrap="true" />
<StackLayout class="dialogInput"> <StackLayout class="dialogInput">
<TextField @loaded="focusField" :hint="hint ? hint : ''" v-model="category" autocapitalizationType="words" @returnPress="$modal.close(category)" /> <TextField
@loaded="focusField"
:hint="hint ? hint : ''"
v-model="category"
autocapitalizationType="words"
@returnPress="$modal.close(category)"
/>
</StackLayout> </StackLayout>
<GridLayout rows="auto" columns="*, auto, auto" class="actionsContainer"> <GridLayout rows="auto" columns="*, auto, auto" class="actionsContainer">
<MDButton :rippleColor="rippleColor" variant="text" col="1" class="action orkm" :text="'cBtn' | L" @tap="$modal.close(false)" /> <MDButton
<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="'cBtn' | L"
@tap="$modal.close(false)"
/>
<MDButton
variant="text"
col="2"
class="action orkm"
:text="`${action}` | L"
@tap="$modal.close(category)"
/>
</GridLayout> </GridLayout>
</StackLayout> </StackLayout>
</Page> </Page>
</template> </template>
<script> <script>
import { import { Application, Utils } from "@nativescript/core";
Application, import { localize } from "@nativescript/localize";
Utils import { mapState } from "vuex";
}
from "@nativescript/core"
import {
localize
}
from '@nativescript/localize'
import {
mapState
}
from "vuex"
export default { export default {
props: ["title", "hint", "text", "action", "helpIcon"], props: ["title", "hint", "text", "action", "helpIcon"],
data() { data() {
return { return {
category: null, category: null,
} };
}, },
computed: { computed: {
...mapState(["icon"]), ...mapState(["icon"]),
appTheme() { appTheme() {
return Application.systemAppearance() return Application.systemAppearance();
}, },
isLightMode() { isLightMode() {
return this.appTheme == "light" return this.appTheme == "light";
},
rippleColor() {
return "rgba(133,133,133,0.2)"
}, },
iconColor() { iconColor() {
return this.isLightMode ? "#f0f0f0" : "#1A1A1A" return this.isLightMode ? "#f0f0f0" : "#1A1A1A";
}, },
}, },
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 = localize( this.text ) this.category = localize(this.text);
} }
}, },
} };
</script> </script>

View file

@ -1,59 +1,80 @@
<template> <template>
<Page> <Page>
<StackLayout class="dialogContainer" :class="appTheme"> <StackLayout class="dialogContainer" :class="appTheme">
<Label class="er dialogIcon" backgroundColor="#858585" :color="iconColor" :text="icon[helpIcon]" /> <Label
class="er dialogIcon"
backgroundColor="#858585"
:color="iconColor"
:text="icon[helpIcon]"
/>
<Label class="dialogTitle orkm" :text="`${title}` | L" /> <Label class="dialogTitle orkm" :text="`${title}` | L" />
<GridLayout rows="auto, auto, auto" columns="*" class="actionsContainer"> <GridLayout rows="auto, auto, auto" columns="*" class="actionsContainer">
<GridLayout
<GridLayout class="shareItem" :backgroundColor="bgColor" row="0" columns="*" rows="auto, auto"> class="shareItem mdr"
<MDRipple :rippleColor="rippleColor" rowSpan="2" @tap="$modal.close('photo')" /> :backgroundColor="bgColor"
row="0"
columns="*"
rows="auto, auto"
@tap="$modal.close('photo')"
>
<Label row="0" class="er" :text="icon.img" /> <Label row="0" class="er" :text="icon.img" />
<Label row="1" class="item" :text="'pht' | L" textWrap="true" /> <Label row="1" class="item" :text="'pht' | L" textWrap="true" />
</GridLayout> </GridLayout>
<GridLayout class="shareItem" :backgroundColor="bgColor" row="1" columns="*" rows="auto, auto"> <GridLayout
<MDRipple :rippleColor="rippleColor" rowSpan="2" @tap="$modal.close('recipe')" /> class="shareItem mdr"
:backgroundColor="bgColor"
row="1"
columns="*"
rows="auto, auto"
@tap="$modal.close('recipe')"
>
<Label row="0" class="er" :text="icon.text" /> <Label row="0" class="er" :text="icon.text" />
<Label row="1" class="item" :text="'rec' | L" textWrap="true" /> <Label row="1" class="item" :text="'rec' | L" textWrap="true" />
</GridLayout> </GridLayout>
<!-- <GridLayout class="shareItem" :backgroundColor="bgColor" row="2" columns="*" rows="auto, auto"> <!-- <GridLayout
<MDRipple :rippleColor="rippleColor" rowSpan="2" @tap="$modal.close('file')" /> class="shareItem mdr"
:backgroundColor="bgColor"
row="2"
columns="*"
rows="auto, auto"
@tap="$modal.close('file')"
>
<Label row="0" class="er" :text="icon.zip" /> <Label row="0" class="er" :text="icon.zip" />
<Label row="1" class="item" :text="'fil' | L" textWrap="true" /> <Label row="1" class="item" :text="'fil' | L" textWrap="true" />
</GridLayout> --> </GridLayout> -->
</GridLayout> </GridLayout>
<GridLayout rows="auto" columns="*, auto" class="actionsContainer"> <GridLayout rows="auto" columns="*, auto" class="actionsContainer">
<MDButton :rippleColor="rippleColor" variant="text" col="1" class="action orkm" :text="'cBtn' | L" @tap="$modal.close()" /> <MDButton
variant="text"
col="1"
class="action orkm mdr"
:text="'cBtn' | L"
@tap="$modal.close()"
/>
</GridLayout> </GridLayout>
</StackLayout> </StackLayout>
</Page> </Page>
</template> </template>
<script> <script>
import { import { Application } from "@nativescript/core";
Application import { mapState } from "vuex";
} from "@nativescript/core"
import {
mapState
} from "vuex"
export default { export default {
props: ["title", "helpIcon"], props: ["title", "helpIcon"],
computed: { computed: {
...mapState(["icon"]), ...mapState(["icon"]),
appTheme() { appTheme() {
return Application.systemAppearance() return Application.systemAppearance();
}, },
isLightMode() { isLightMode() {
return this.appTheme == "light" return this.appTheme == "light";
},
rippleColor() {
return "rgba(133,133,133,0.2)"
}, },
iconColor() { iconColor() {
return this.isLightMode ? "#f0f0f0" : "#1A1A1A" return this.isLightMode ? "#f0f0f0" : "#1A1A1A";
}, },
bgColor() { bgColor() {
return this.isLightMode ? "#fff" : "#292929" return this.isLightMode ? "#fff" : "#292929";
}, },
}, },
} };
</script> </script>

View file

@ -1,51 +1,54 @@
import {localize, androidLaunchEventLocalizationHandler} from '@nativescript/localize' import {
import {on, launchEvent} from '@nativescript/core/application'; localize,
androidLaunchEventLocalizationHandler,
} from '@nativescript/localize'
import { on, launchEvent } from '@nativescript/core/application'
on(launchEvent, (args) => { on(launchEvent, (args) => {
if (args.android) { if (args.android) {
androidLaunchEventLocalizationHandler(); 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'
import {install} from '@nativescript-community/ui-drawer'; import { installMixins } from '@nativescript-community/ui-material-core'
install(); installMixins()
import DrawerPlugin from '@nativescript-community/ui-drawer/vue'; import { install } from '@nativescript-community/ui-drawer'
Vue.use(DrawerPlugin); install()
// import CollectionView from '@nativescript-community/ui-collectionview/vue'; import DrawerPlugin from '@nativescript-community/ui-drawer/vue'
// Vue.use(CollectionView); Vue.use(DrawerPlugin)
import ButtonPlugin from "@nativescript-community/ui-material-button/vue" import CollectionView from '@nativescript-community/ui-collectionview/vue';
Vue.use(CollectionView);
import ButtonPlugin from '@nativescript-community/ui-material-button/vue'
Vue.use(ButtonPlugin) Vue.use(ButtonPlugin)
import ActivityIndicatorPlugin from "@nativescript-community/ui-material-activityindicator/vue" import ActivityIndicatorPlugin from '@nativescript-community/ui-material-activityindicator/vue'
Vue.use(ActivityIndicatorPlugin) Vue.use(ActivityIndicatorPlugin)
import RipplePlugin from "@nativescript-community/ui-material-ripple/vue" import FloatingActionButtonPlugin from '@nativescript-community/ui-material-floatingactionbutton/vue'
Vue.use(RipplePlugin)
import FloatingActionButtonPlugin from "@nativescript-community/ui-material-floatingactionbutton/vue"
Vue.use(FloatingActionButtonPlugin) Vue.use(FloatingActionButtonPlugin)
import ProgressPlugin from "@nativescript-community/ui-material-progress/vue" import ProgressPlugin from '@nativescript-community/ui-material-progress/vue'
Vue.use(ProgressPlugin) Vue.use(ProgressPlugin)
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',
event: "checkedChange" event: 'checkedChange',
} },
}) })
Vue.config.silent = TNS_ENV === "production" Vue.config.silent = TNS_ENV === 'production'
Vue.filter('L', localize) Vue.filter('L', localize)
new Vue({ new Vue({
store, store,
render: h => h("frame", [h(App)]) render: (h) => h('frame', [h(App)]),
}).$start() }).$start()

15399
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -7,12 +7,12 @@
"dependencies": { "dependencies": {
"@nativescript-community/gesturehandler": "^0.1.36", "@nativescript-community/gesturehandler": "^0.1.36",
"@nativescript-community/perms": "^2.1.4", "@nativescript-community/perms": "^2.1.4",
"@nativescript-community/ui-collectionview": "^4.0.24",
"@nativescript-community/ui-drawer": "0.0.22", "@nativescript-community/ui-drawer": "0.0.22",
"@nativescript-community/ui-material-activityindicator": "^5.1.16", "@nativescript-community/ui-material-activityindicator": "^5.1.16",
"@nativescript-community/ui-material-button": "^5.1.16", "@nativescript-community/ui-material-button": "^5.1.16",
"@nativescript-community/ui-material-floatingactionbutton": "^5.1.16", "@nativescript-community/ui-material-floatingactionbutton": "^5.1.16",
"@nativescript-community/ui-material-progress": "^5.1.16", "@nativescript-community/ui-material-progress": "^5.1.16",
"@nativescript-community/ui-material-ripple": "^5.1.16",
"@nativescript-community/ui-material-snackbar": "^5.1.16", "@nativescript-community/ui-material-snackbar": "^5.1.16",
"@nativescript/core": "~7.0.0", "@nativescript/core": "~7.0.0",
"@nativescript/localize": "^5.0.2", "@nativescript/localize": "^5.0.2",