enrecipes/app/components/EnRecipes.vue

1120 lines
34 KiB
Vue
Raw Normal View History

2020-09-15 11:10:16 +00:00
<template>
2021-04-01 10:55:35 +00:00
<Frame @loaded="onFrameLoad" :class="appTheme">
<Page @loaded="onPageLoad" @unloaded="onPageUnload" actionBarHidden="true">
<GridLayout rows="*, auto, auto" columns="*">
<CollectionView
rowSpan="3"
:spanSize="getSpanSize"
for="recipe in getList"
@loaded="onListLoad"
:itemTemplateSelector="getLayout"
2021-04-12 18:09:48 +00:00
:colWidth="layout == 'grid' || layout == 'photogrid' ? '50%' : '100%'"
2021-04-01 10:55:35 +00:00
@scroll="!selectMode && onScroll($event)"
>
<v-template name="header">
<GridLayout rows="auto" columns="*, auto, 12">
<Label class="pageTitle" :text="`${currentComponent}` | L" />
<Button
col="1"
class="ico"
:text="icon.cog"
@tap="navigateTo(Settings, 'Settings', true)"
/>
</GridLayout>
</v-template>
<v-template name="lists">
<StackLayout orientation="horizontal" padding="0 16 16">
<GridLayout
rows="48"
columns="auto, auto"
class="segment"
v-for="(item, index) in topmenu"
:key="index"
:class="{
2021-04-12 18:09:48 +00:00
select: currentComponent === item.title,
2021-04-01 10:55:35 +00:00
}"
2021-04-12 18:09:48 +00:00
@touch="touchSelector($event, item.title, item.title)"
2021-04-01 10:55:35 +00:00
>
<Label class="ico" :text="icon[item.icon]" />
<Label
class="value"
2021-04-12 18:09:48 +00:00
:hidden="!getRecipeCount(item.title)"
2021-04-01 10:55:35 +00:00
:text="getRecipeCount(item.title)"
col="1"
/>
</GridLayout>
<GridLayout
2021-04-12 18:09:48 +00:00
:hidden="currentComponent !== 'Filtered recipes'"
2021-04-01 10:55:35 +00:00
rows="48"
columns="auto, auto"
class="segment"
:class="{
select: currentComponent === 'Filtered recipes',
}"
>
2021-04-12 18:09:48 +00:00
<Label class="ico" :text="icon.filter" />
2021-04-01 10:55:35 +00:00
<Label
class="value"
:text="getRecipeCount('filtered')"
col="1"
/>
</GridLayout>
</StackLayout>
</v-template>
<v-template name="detailed">
2021-02-28 15:10:26 +00:00
<GridLayout
2021-04-01 10:55:35 +00:00
class="recipeItem"
:class="getItemPos(recipe.id)"
2021-04-12 18:09:48 +00:00
rows="auto"
2021-03-23 06:16:25 +00:00
columns="96, *"
2021-02-28 15:10:26 +00:00
ref="recipe"
@longPress="
2021-04-01 10:55:35 +00:00
selectMode ? viewRecipe(recipe.id) : addToSelection(recipe.id)
2021-02-28 15:10:26 +00:00
"
@tap="
2021-04-01 10:55:35 +00:00
selectMode ? addToSelection(recipe.id) : viewRecipe(recipe.id)
2021-02-28 15:10:26 +00:00
"
>
2021-04-01 10:55:35 +00:00
<Image
class="imgHolder"
2021-04-12 18:09:48 +00:00
verticalAlignment="top"
2021-04-01 10:55:35 +00:00
v-if="recipe.imageSrc"
:src="recipe.imageSrc"
2021-04-12 18:09:48 +00:00
stretch="none"
2021-04-01 10:55:35 +00:00
decodeWidth="96"
decodeHeight="96"
loadMode="async"
/>
<Label
v-else
class="ico imgHolder"
2021-04-12 18:09:48 +00:00
verticalAlignment="top"
2021-04-01 10:55:35 +00:00
@loaded="centerLabel"
width="96"
height="96"
fontSize="48"
:text="icon.img"
/>
2021-02-28 15:10:26 +00:00
<StackLayout class="recipeInfo" col="1">
2021-04-12 18:09:48 +00:00
<Label :text="recipe.title" class="tb title tw" />
<StackLayout class="attributes" orientation="horizontal"
><Label class="ico sm" :text="icon.cuisine" />
2021-04-01 10:55:35 +00:00
<Label class="attr" :text="recipe.cuisine | L" />
<Label class="ico sm" :text="icon.category" />
<Label class="attr" :text="recipe.category | L" />
</StackLayout>
<StackLayout
2021-04-12 18:09:48 +00:00
:hidden="!recipe.tags.length"
2021-04-01 10:55:35 +00:00
class="attributes"
orientation="horizontal"
>
<Label class="ico sm" :text="icon.tag" />
<Label class="attr" :text="getTags(recipe.tags)" />
</StackLayout>
<StackLayout class="attributes" orientation="horizontal">
<Label class="ico sm" :text="icon.star" />
<Label class="attr" :text="recipe.rating" />
<Label class="ico sm" :text="icon.time" />
<Label
class="attr"
:text="`${
formattedTotalTime(recipe.prepTime, recipe.cookTime).time
}`"
/>
<Label class="ico sm" :text="icon.diff" />
<Label class="attr" :text="recipe.difficulty | L" />
</StackLayout>
2021-02-28 15:10:26 +00:00
</StackLayout>
2021-01-23 17:20:15 +00:00
</GridLayout>
2021-04-01 10:55:35 +00:00
</v-template>
<v-template name="grid">
2021-02-28 15:10:26 +00:00
<GridLayout
2021-04-01 10:55:35 +00:00
class="recipeItem grid"
:class="getItemPos(recipe.id)"
rows="auto, auto"
2021-02-28 15:10:26 +00:00
columns="*"
ref="recipe"
@longPress="
2021-04-01 10:55:35 +00:00
selectMode ? viewRecipe(recipe.id) : addToSelection(recipe.id)
2021-02-28 15:10:26 +00:00
"
@tap="
2021-04-01 10:55:35 +00:00
selectMode ? addToSelection(recipe.id) : viewRecipe(recipe.id)
2021-02-28 15:10:26 +00:00
"
>
2021-04-01 10:55:35 +00:00
<Image
class="imgHolder"
v-if="recipe.imageSrc"
:src="recipe.imageSrc"
stretch="aspectFit"
:decodeWidth="imgWidth"
:decodeHeight="imgWidth"
loadMode="async"
/>
<Label
v-else
width="100%"
:height="imgWidth"
@loaded="centerLabel"
class="ico imgHolder"
:fontSize="imgWidth / 2"
:text="icon.img"
/>
<StackLayout class="recipeInfo" row="1">
2021-04-12 18:09:48 +00:00
<Label :text="recipe.title" class="tb title tw" />
2021-04-01 10:55:35 +00:00
<StackLayout class="attributes" orientation="horizontal">
<Label class="ico sm" :text="icon.cuisine" />
<Label class="attr" :text="recipe.cuisine | L" />
</StackLayout>
<StackLayout class="attributes" orientation="horizontal">
<Label class="ico sm" :text="icon.category" />
<Label class="attr" :text="recipe.category | L" />
</StackLayout>
2021-02-28 15:10:26 +00:00
<StackLayout
2021-04-12 18:09:48 +00:00
:hidden="!recipe.tags.length"
2021-04-01 10:55:35 +00:00
class="attributes"
2021-02-28 15:10:26 +00:00
orientation="horizontal"
>
2021-04-01 10:55:35 +00:00
<Label class="ico sm" :text="icon.tag" />
<Label class="attr" :text="getTags(recipe.tags)" />
2021-02-28 15:10:26 +00:00
</StackLayout>
2021-01-23 17:20:15 +00:00
</StackLayout>
2021-02-28 15:10:26 +00:00
</GridLayout>
2021-04-01 10:55:35 +00:00
</v-template>
2021-04-12 18:09:48 +00:00
<v-template name="photogrid">
<GridLayout
class="recipeItem grid"
:class="getItemPos(recipe.id)"
rows="auto, auto"
columns="*"
ref="recipe"
@longPress="
selectMode ? viewRecipe(recipe.id) : addToSelection(recipe.id)
"
@tap="
selectMode ? addToSelection(recipe.id) : viewRecipe(recipe.id)
"
>
<Image
class="imgHolder"
v-if="recipe.imageSrc"
:src="recipe.imageSrc"
stretch="aspectFit"
:decodeWidth="imgWidth"
:decodeHeight="imgWidth"
loadMode="async"
/>
<Label
v-else
width="100%"
:height="imgWidth"
@loaded="centerLabel"
class="ico imgHolder"
:fontSize="imgWidth / 2"
:text="icon.img"
/>
<StackLayout class="recipeInfo" row="1">
<Label :text="recipe.title" class="tb title tw" />
</StackLayout>
</GridLayout>
</v-template>
2021-04-01 10:55:35 +00:00
<v-template name="simple">
2021-02-28 15:10:26 +00:00
<GridLayout
2021-04-01 10:55:35 +00:00
class="recipeItem simple"
:class="getItemPos(recipe.id)"
2021-02-28 15:10:26 +00:00
columns="*"
ref="recipe"
@longPress="
2021-04-01 10:55:35 +00:00
selectMode ? viewRecipe(recipe.id) : addToSelection(recipe.id)
2021-02-28 15:10:26 +00:00
"
@tap="
2021-04-01 10:55:35 +00:00
selectMode ? addToSelection(recipe.id) : viewRecipe(recipe.id)
2021-02-28 15:10:26 +00:00
"
>
2021-04-01 10:55:35 +00:00
<StackLayout class="recipeInfo">
2021-04-12 18:09:48 +00:00
<Label :text="recipe.title" class="tb title tw" />
2021-04-01 10:55:35 +00:00
<StackLayout class="attributes" orientation="horizontal">
<Label class="ico sm" :text="icon.cuisine" />
<Label class="attr" :text="recipe.cuisine | L" />
<Label class="ico sm" :text="icon.category" />
<Label class="attr" :text="recipe.category | L" />
</StackLayout>
2021-03-21 17:02:04 +00:00
<StackLayout
2021-04-12 18:09:48 +00:00
:hidden="!recipe.tags.length"
2021-04-01 10:55:35 +00:00
class="attributes"
2021-03-21 17:02:04 +00:00
orientation="horizontal"
>
2021-04-01 10:55:35 +00:00
<Label class="ico sm" :text="icon.tag" />
<Label class="attr" :text="getTags(recipe.tags)" />
2021-02-28 15:10:26 +00:00
</StackLayout>
2021-01-23 17:20:15 +00:00
</StackLayout>
2021-02-28 15:10:26 +00:00
</GridLayout>
2021-04-01 10:55:35 +00:00
</v-template>
<v-template name="minimal">
<GridLayout
class="recipeItem simple minimal"
:class="getItemPos(recipe.id)"
columns="*"
ref="recipe"
@longPress="
selectMode ? viewRecipe(recipe.id) : addToSelection(recipe.id)
"
@tap="
selectMode ? addToSelection(recipe.id) : viewRecipe(recipe.id)
"
>
<StackLayout class="recipeInfo">
2021-04-12 18:09:48 +00:00
<Label :text="recipe.title" class="tb title tw" />
2021-04-01 10:55:35 +00:00
</StackLayout>
</GridLayout>
</v-template>
</CollectionView>
<GridLayout rowSpan="2" rows="*, auto" columns="*">
<StackLayout
row="1"
class="emptyState"
v-if="!recipes.length && !filterFavourites && !filterTrylater"
>
<Label class="title" :text="'strAdd' | L" />
<Label :text="'plsAdd' | L" />
2021-02-28 15:10:26 +00:00
</StackLayout>
2021-04-01 10:55:35 +00:00
<StackLayout
row="1"
class="emptyState"
v-if="!filteredRecipes.length && filterTrylater && !searchQuery"
>
<Label class="title" :text="'aD' | L" />
<Label :text="'tLInfo' | L" />
</StackLayout>
<StackLayout
row="1"
class="emptyState"
v-if="!filteredRecipes.length && filterFavourites && !searchQuery"
>
<Label class="title" :text="'noFavs' | L" />
<Label :text="'fsList' | L" />
</StackLayout>
<StackLayout
row="1"
class="emptyState"
v-if="!filteredRecipes.length && searchQuery"
>
<Label class="title" :text="`${noResultFor}` | L" />
<Button
v-if="filterFavourites || filterTrylater || selectedCuisine"
class="text big"
:text="'trySer' | L"
@tap="goToHome"
/>
</StackLayout>
</GridLayout>
<GridLayout
2021-02-28 15:10:26 +00:00
row="1"
2021-04-01 10:55:35 +00:00
rows="auto"
columns="auto"
class="appbar toolbar"
2021-04-12 18:09:48 +00:00
:hidden="!showTools"
2021-02-28 15:10:26 +00:00
>
2021-04-01 10:55:35 +00:00
<GridLayout
row="1"
rows="48"
class="tool"
columns="auto, *"
@touch="touchTool($event, MealPlanner, 'MealPlanner')"
>
<Label class="ico" :text="icon.cal" />
<Label col="1" :text="'planner' | L" />
</GridLayout>
</GridLayout>
<GridLayout
row="2"
@loaded="onAppBarLoad"
class="appbar"
columns="auto, *, auto, auto, auto, auto"
2021-02-28 15:10:26 +00:00
>
2021-04-01 10:55:35 +00:00
<Button
class="ico"
@tap="
showSearch
? closeSearch()
: selectMode
? clearSelection()
: toggleTools()
"
:text="
showSearch
? icon.back
: selectMode || showTools
? icon.x
: icon.menu
"
/>
<TextField
id="searchBar"
@loaded="focusField"
v-if="showSearch"
col="1"
colSpan="5"
:hint="'ser' | L"
@textChange="updateList($event.value)"
/>
2021-02-28 15:10:26 +00:00
<Label
2021-04-12 18:09:48 +00:00
:hidden="!selectMode"
2021-04-01 10:55:35 +00:00
class="title"
:text="`${selection.length} ${$options.filters.L('sltd')}`"
col="1"
2021-02-28 15:10:26 +00:00
/>
2021-04-12 18:09:48 +00:00
<StackLayout
2021-04-01 10:55:35 +00:00
col="2"
2021-04-12 18:09:48 +00:00
colSpan="3"
orientation="horizontal"
:hidden="!recipes.length || selectMode || showSearch"
>
<Button
class="ico"
:text="selectMode ? icon.exp : icon.sear"
@tap="selectMode ? exportSelection() : openSearch()"
/>
<Button class="ico" :text="icon.sort" @tap="openSort" />
<Button class="ico" :text="icon.filter" @tap="openFilters" />
</StackLayout>
2021-04-01 10:55:35 +00:00
<Button
2021-04-12 18:09:48 +00:00
:hidden="showSearch || selectMode"
2021-04-01 10:55:35 +00:00
class="ico fab"
:text="icon.plus"
col="5"
2021-04-12 18:09:48 +00:00
@tap="addRecipe"
2021-04-01 10:55:35 +00:00
/>
<Button
2021-04-12 18:09:48 +00:00
:hidden="!selectMode"
2021-04-01 10:55:35 +00:00
class="ico"
:text="icon.del"
col="5"
@tap="deleteSelection"
2021-02-28 15:10:26 +00:00
/>
2021-04-01 10:55:35 +00:00
</GridLayout>
2021-02-28 15:10:26 +00:00
</GridLayout>
2021-04-01 10:55:35 +00:00
</Page>
</Frame>
2020-09-15 11:10:16 +00:00
</template>
2021-04-01 10:55:35 +00:00
2020-09-15 11:10:16 +00:00
<script>
import {
2020-12-29 10:35:19 +00:00
ApplicationSettings,
AndroidApplication,
2021-04-01 10:55:35 +00:00
Application,
Utils,
2020-12-29 10:35:19 +00:00
Observable,
Device,
2021-02-28 15:10:26 +00:00
Screen,
2021-04-01 10:55:35 +00:00
Color,
2021-04-12 18:09:48 +00:00
CoreTypes,
2021-02-28 15:10:26 +00:00
} from "@nativescript/core";
import { localize } from "@nativescript/localize";
2020-12-29 10:35:19 +00:00
import {
startAccelerometerUpdates,
stopAccelerometerUpdates,
2021-03-23 06:16:25 +00:00
} from "@triniwiz/nativescript-accelerometer";
2021-02-28 15:10:26 +00:00
import { mapActions, mapState } from "vuex";
2021-04-01 10:55:35 +00:00
import ViewRecipe from "./ViewRecipe";
import EditRecipe from "./EditRecipe";
import MealPlanner from "./MealPlanner";
import GroceryList from "./GroceryList";
import Settings from "./Settings";
import ActionDialog from "./modal/ActionDialog.vue";
import ConfirmDialog from "./modal/ConfirmDialog.vue";
2021-04-01 10:55:35 +00:00
import Filters from "./modal/Filters.vue";
2021-04-12 18:09:48 +00:00
import * as utils from "~/shared/utils";
2020-12-29 10:35:19 +00:00
let lastTime = 0;
let lastShake = 0;
let lastForce = 0;
let shakeCount = 0;
2021-01-13 05:02:48 +00:00
let typingTimer;
2021-04-01 10:55:35 +00:00
let filterTimer;
2020-10-14 19:32:32 +00:00
export default {
2020-09-15 11:10:16 +00:00
data() {
return {
2020-10-14 19:32:32 +00:00
searchQuery: "",
2020-10-21 17:54:45 +00:00
showSearch: false,
deletionDialogActive: false,
2021-01-23 17:20:15 +00:00
selection: [],
selectMode: false,
2021-04-01 10:55:35 +00:00
listview: null,
appbar: null,
scrollPos: 1,
filterFavourites: false,
filterTrylater: false,
MealPlanner: MealPlanner,
GroceryList: GroceryList,
Settings: Settings,
topmenu: [
{
title: "EnRecipes",
icon: "home",
},
{
title: "trylater",
icon: "try",
},
{
title: "favourites",
icon: "fav",
},
],
showTools: false,
};
2020-09-15 11:10:16 +00:00
},
2021-04-01 10:55:35 +00:00
components: {
ViewRecipe,
EditRecipe,
MealPlanner,
GroceryList,
Settings,
},
2020-09-15 11:10:16 +00:00
computed: {
2021-02-28 15:10:26 +00:00
...mapState([
"icon",
2021-04-01 10:55:35 +00:00
"sortType",
2021-02-28 15:10:26 +00:00
"recipes",
2021-04-01 10:55:35 +00:00
"cuisines",
"categories",
"yieldUnits",
"mealPlans",
2021-02-28 15:10:26 +00:00
"shakeEnabled",
2021-04-01 10:55:35 +00:00
"currentComponent",
2021-03-21 17:02:04 +00:00
"layout",
2021-04-01 10:55:35 +00:00
"selectedCuisine",
"selectedCategory",
"selectedTag",
"appTheme",
2021-02-28 15:10:26 +00:00
]),
2020-09-15 11:10:16 +00:00
filteredRecipes() {
2021-02-28 15:10:26 +00:00
let vm = this;
function getIngredients(e) {
return e.ingredients
.map((f) => f.item.toLowerCase())
.join()
.includes(vm.searchQuery);
2021-01-13 05:02:48 +00:00
}
2021-02-28 15:10:26 +00:00
if (this.filterFavourites) {
return this.recipes
.filter(
(e) =>
e.isFavorite &&
(e.title.toLowerCase().includes(this.searchQuery) ||
getIngredients(e))
)
.sort(this.sortFunction);
} else if (this.filterTrylater) {
return this.recipes
.filter(
(e) =>
!e.tried &&
(e.title.toLowerCase().includes(this.searchQuery) ||
getIngredients(e))
)
.sort(this.sortFunction);
} else if (this.selectedCuisine) {
return this.recipes
.filter((e) => {
return (
this.recipeFilter(e) &&
(e.title.toLowerCase().includes(this.searchQuery) ||
getIngredients(e))
);
})
.sort(this.sortFunction);
2020-12-14 13:48:53 +00:00
} else {
2021-02-28 15:10:26 +00:00
return this.recipes
.filter(
(e) =>
e.title.toLowerCase().includes(this.searchQuery) ||
getIngredients(e)
)
.sort(this.sortFunction);
2020-09-15 11:10:16 +00:00
}
2021-04-01 10:55:35 +00:00
},
getList() {
return [{}, {}].concat(this.filteredRecipes);
2020-09-15 11:10:16 +00:00
},
2020-11-28 19:21:57 +00:00
noResultFor() {
2021-04-17 16:24:47 +00:00
if (this.filterFavourites || this.filterTrylater || this.selectedCuisine)
return "noRecsInL";
2021-01-13 05:02:48 +00:00
return "noRecs";
2020-12-29 10:35:19 +00:00
},
2021-01-23 17:20:15 +00:00
imgWidth() {
2021-04-01 10:55:35 +00:00
return Screen.mainScreen.widthDIPs / 2 - 24;
2021-01-23 17:20:15 +00:00
},
2020-09-15 11:10:16 +00:00
},
methods: {
2021-02-28 15:10:26 +00:00
...mapActions([
2021-04-01 10:55:35 +00:00
"setComponent",
"initListItems",
"initRecipes",
"initMealPlans",
2021-04-12 18:09:48 +00:00
"setShake",
"setFirstDay",
2021-04-01 10:55:35 +00:00
"setLayout",
2021-04-12 18:09:48 +00:00
"setSortType",
2021-02-28 15:10:26 +00:00
"deleteRecipeAction",
"deleteRecipesAction",
2021-04-01 10:55:35 +00:00
"clearFilter",
"setTheme",
2021-02-28 15:10:26 +00:00
]),
2021-04-01 10:55:35 +00:00
onFrameLoad() {
const View = android.view.View;
const window = Application.android.startActivity.getWindow();
const decorView = window.getDecorView();
let sdkv = Device.sdkVersion;
function setColors(color) {
window.setStatusBarColor(new Color(color).android);
sdkv >= 27 && window.setNavigationBarColor(new Color(color).android);
}
switch (this.appTheme) {
case "Light":
setColors("#f1f3f5");
break;
case "Dark":
setColors("#212529");
break;
default:
setColors("#000000");
break;
}
2021-04-12 18:09:48 +00:00
if (sdkv >= 27)
2021-04-18 13:28:25 +00:00
decorView.setSystemUiVisibility(
this.appTheme == "Light"
? View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR |
View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
: View.SYSTEM_UI_FLAG_DARK_STATUS_BAR |
View.SYSTEM_UI_FLAG_DARK_NAVIGATION_BAR
);
else
decorView.setSystemUiVisibility(
this.appTheme == "Light"
? View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
: View.SYSTEM_UI_FLAG_DARK_STATUS_BAR
);
2021-04-01 10:55:35 +00:00
},
2021-02-28 15:10:26 +00:00
onPageLoad(args) {
const page = args.object;
page.bindingContext = new Observable();
2021-02-28 15:10:26 +00:00
this.filterFavourites
2021-04-12 18:09:48 +00:00
? this.setComponent("favourites")
2021-02-28 15:10:26 +00:00
: this.filterTrylater
2021-04-12 18:09:48 +00:00
? this.setComponent("trylater")
2021-02-28 15:10:26 +00:00
: this.selectedCuisine
? this.setComponent("Filtered recipes")
: this.setComponent("EnRecipes");
2021-02-28 17:34:27 +00:00
if (this.shakeEnabled) {
if (utils.hasAccelerometer())
startAccelerometerUpdates((data) => this.onSensorData(data));
2021-04-12 18:09:48 +00:00
else this.setShake(false);
2021-02-28 17:34:27 +00:00
}
2021-04-01 10:55:35 +00:00
this.hijackBackEvent();
setTimeout(() => {
if (this.listview) this.listview.refresh();
}, 1000);
this.showTools = false;
},
onPageUnload() {
2021-02-28 15:10:26 +00:00
if (this.shakeEnabled) stopAccelerometerUpdates();
},
2021-04-01 10:55:35 +00:00
onAppBarLoad({ object }) {
this.appbar = object;
},
// COLLECTIONVIEW
onListLoad({ object }) {
const View = android.view.View;
object.android.setOverScrollMode(View.OVER_SCROLL_NEVER);
this.listview = object;
},
onScroll(args) {
this.showTools = false;
let scrollUp;
let y = args.object.scrollOffset;
if (y) {
scrollUp = y < this.scrollPos;
this.scrollPos = Math.abs(y);
let ab = this.appbar.translateY;
if (!scrollUp && ab == 0) {
2021-04-12 18:09:48 +00:00
this.appbar.animate({
translate: { x: 0, y: 64 },
duration: 250,
curve: CoreTypes.AnimationCurve.ease,
});
2021-04-01 10:55:35 +00:00
} else if (scrollUp && ab == 64) {
2021-04-12 18:09:48 +00:00
this.appbar.animate({
translate: { x: 0, y: 0 },
duration: 250,
curve: CoreTypes.AnimationCurve.ease,
});
2021-04-01 10:55:35 +00:00
}
}
},
getSpanSize(index) {
2021-04-12 18:09:48 +00:00
return (this.layout == "grid" || this.layout == "photogrid") &&
(index == 0 || index == 1)
? 2
: 1;
2020-11-23 09:49:58 +00:00
},
2021-04-01 10:55:35 +00:00
getLayout(args, index, items) {
return index == 0 ? "header" : index == 1 ? "lists" : this.layout;
2021-01-23 17:20:15 +00:00
},
2021-04-01 10:55:35 +00:00
// SEARCH
2020-10-21 17:54:45 +00:00
openSearch() {
2021-04-01 10:55:35 +00:00
this.showTools = false;
2021-03-23 09:59:00 +00:00
this.showSearch = true;
},
2020-11-10 18:28:48 +00:00
closeSearch() {
this.searchQuery = "";
Utils.ad.dismissSoftInput();
this.showSearch = false;
2020-11-10 18:28:48 +00:00
},
2021-04-01 10:55:35 +00:00
//SORT
openSort() {
this.showTools = false;
this.releaseBackEvent();
this.$showModal(ActionDialog, {
props: {
title: "srt",
list: [
2021-04-12 18:09:48 +00:00
"title",
2021-04-01 10:55:35 +00:00
"Rating",
"Quickest first",
"Slowest first",
"Difficulty level",
"Last updated",
"Newest first",
"Oldest first",
],
},
}).then((action) => {
if (action && action !== "Cancel" && this.sortType !== action) {
2021-04-12 18:09:48 +00:00
this.setSortType(action);
2021-04-01 10:55:35 +00:00
ApplicationSettings.setString("sortType", action);
this.updateSort();
}
this.hijackBackEvent();
});
},
//FILTER
openFilters() {
2021-04-12 18:09:48 +00:00
this.setComponent("EnRecipes");
this.filterFavourites = this.filterTrylater = false;
2021-04-01 10:55:35 +00:00
this.showTools = false;
this.releaseBackEvent();
this.$showModal(Filters).then(() => this.hijackBackEvent());
},
// TOOLS
toggleTools() {
this.showTools = !this.showTools;
},
// LIST HANDLERS
addToSelection(id) {
this.showTools = false;
this.selectMode = true;
this.appbar.translateY = 0;
this.selection.includes(id)
? this.selection.splice(this.selection.indexOf(id), 1)
: this.selection.push(id);
this.selection.length ? this.listview.refresh() : this.clearSelection();
},
clearSelection() {
this.selectMode = false;
this.selection = [];
this.listview.refresh();
},
deleteSelection() {
this.selection.length === 1
? this.deleteRecipe(this.selection[0])
: this.deleteRecipes(this.selection);
},
exportSelection() {},
deleteRecipe(id) {
this.deletionDialogActive = true;
let index = this.recipes.findIndex((e) => e.id === id);
2021-04-17 16:24:47 +00:00
let recipeTitle = `"${this.recipes[index].title}"`;
2021-04-01 10:55:35 +00:00
this.$showModal(ConfirmDialog, {
props: {
title: localize("conf"),
2021-04-17 16:24:47 +00:00
description: `${localize("delRecInfo", recipeTitle)}`,
2021-04-01 10:55:35 +00:00
cancelButtonText: "cBtn",
okButtonText: "dBtn",
},
}).then((action) => {
if (action) {
this.deleteRecipeAction({
index,
id,
});
if (!this.filteredRecipes.length) this.goToHome();
this.clearSelection();
}
this.deletionDialogActive = false;
});
},
deleteRecipes(idsArr) {
this.deletionDialogActive = true;
2021-04-17 16:24:47 +00:00
let selectionCount = `${this.selection.length} ${localize("recs")}`;
2021-04-01 10:55:35 +00:00
this.$showModal(ConfirmDialog, {
props: {
title: localize("conf"),
2021-04-17 16:24:47 +00:00
description: `${localize("delRecsInfo", selectionCount)}`,
2021-04-01 10:55:35 +00:00
cancelButtonText: "cBtn",
okButtonText: "dBtn",
},
}).then((action) => {
if (action) {
this.deleteRecipesAction(idsArr);
if (!this.filteredRecipes.length) this.goToHome();
this.clearSelection();
}
this.deletionDialogActive = false;
});
},
// SHAKE DETECTOR
onSensorData({ x, y, z }) {
x = x.toFixed(2);
y = y.toFixed(2);
z = z.toFixed(2);
const FORCE_THRESHOLD = 1;
const TIME_THRESHOLD = 150;
const SHAKE_TIMEOUT = 600;
const SHAKE_THROTTLE = 600;
const SHAKE_COUNT = 3;
const now = Date.now();
if (now - lastForce > SHAKE_TIMEOUT) {
shakeCount = 0;
}
let timeDelta = now - lastTime;
if (timeDelta > TIME_THRESHOLD) {
let forceVector = Math.abs(
Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2)) - 1
);
if (forceVector > FORCE_THRESHOLD) {
shakeCount++;
if (shakeCount >= SHAKE_COUNT && now - lastShake > SHAKE_THROTTLE) {
lastShake = now;
shakeCount = 0;
if (this.filteredRecipes.length) {
utils.vibrate(100);
this.viewRandomRecipe();
}
}
lastForce = now;
}
lastTime = now;
}
},
// HELPERS
getRecipeCount(arg) {
let count = 0;
let a = this.selectedCuisine;
let b = this.selectedCategory;
let c = this.selectedTag;
let cuisine = a && a != "allCuis";
let category = b && b != "allCats";
let tag = c && c != "allTs";
let allCuisines = a && a == "allCuis";
let allCategories = b && b == "allCats";
let allTags = c && c == "allTs";
switch (arg) {
case "EnRecipes":
count = this.recipes.length;
break;
case "trylater":
count = this.recipes.filter((e) => !e.tried).length;
break;
case "favourites":
count = this.recipes.filter((e) => e.isFavorite).length;
break;
default:
count = this.recipes.filter((e) => {
let cui = e.cuisine === a;
let cat = e.category === b;
let t = e.tags.includes(c);
return allCuisines
? allCategories
? tag
? t
: true
: category
? allTags
? cat
: tag
? cat && t
: cat
: true
: cuisine
? allCategories
? allTags
? cui
: tag
? cui && t
: cui
: category
? allTags
? cui && cat
: tag
? cui && cat && t
: cui && cat
: cui
: false;
}).length;
break;
}
return count;
},
centerLabel(args) {
args.object.android.setGravity(17);
},
focusField(args) {
setTimeout((e) => {
args.object.focus();
setTimeout((e) => Utils.ad.showSoftInput(args.object.android), 100);
}, 100);
2020-11-10 18:28:48 +00:00
},
2021-02-28 15:10:26 +00:00
updateList(value) {
clearTimeout(typingTimer);
typingTimer = setTimeout((e) => {
2021-03-23 09:59:00 +00:00
this.searchQuery = value.toLowerCase();
2021-02-28 15:10:26 +00:00
}, 750);
},
formattedTotalTime(prepTime, cookTime) {
let t1 = prepTime.split(":");
let t2 = cookTime.split(":");
let minutes = parseInt(t1[1]) + parseInt(t2[1]);
let m = minutes % 60;
let h = parseInt(t1[0]) + parseInt(t2[0]) + Math.floor(minutes / 60);
let hr = localize("hr");
let min = localize("min");
let mins = h * 60 + m;
2020-11-10 18:28:48 +00:00
return {
2021-02-28 15:10:26 +00:00
time: h ? (m ? `${h} ${hr} ${m} ${min}` : `${h} ${hr}`) : `${m} ${min}`,
duration: `${mins}`,
};
2020-11-10 18:28:48 +00:00
},
2021-02-28 15:10:26 +00:00
randomRecipeID() {
// TODO: show only from selected filter
let min = 0;
let max = this.filteredRecipes.length - 1;
let randomIndex = Math.round(Math.random() * (max - min));
return this.filteredRecipes[randomIndex].id;
},
recipeFilter(e) {
let cuisineMatched = e.cuisine === this.selectedCuisine;
let allCuisines = /allCuis/.test(this.selectedCuisine);
let categoryMatched = e.category === this.selectedCategory;
let allCategories = /allCats/.test(this.selectedCategory);
let tagMatched = e.tags.includes(this.selectedTag);
let allTags = /allTs/.test(this.selectedTag);
let cuisine = cuisineMatched || allCuisines;
2020-12-29 10:35:19 +00:00
2021-02-28 15:10:26 +00:00
return this.selectedTag && !allTags
? (categoryMatched || allCategories) && cuisine && tagMatched
: this.selectedCategory && !allCategories
? cuisine && categoryMatched
: cuisine;
2020-12-29 10:35:19 +00:00
},
2021-02-28 15:10:26 +00:00
sortFunction(a, b) {
const titleOrder = a.title
.toLowerCase()
.localeCompare(b.title.toLowerCase(), Device.language, {
ignorePunctuation: true,
});
let d1 = this.formattedTotalTime(a.prepTime, a.cookTime).duration;
let d2 = this.formattedTotalTime(b.prepTime, b.cookTime).duration;
let ld1 = new Date(a.lastModified);
let ld2 = new Date(b.lastModified);
let cd1 = new Date(a.created);
let cd2 = new Date(b.created);
let r1 = a.rating;
let r2 = b.rating;
2021-01-23 17:20:15 +00:00
2021-02-28 15:10:26 +00:00
function difficultyLevel(l) {
switch (l) {
2021-01-23 17:20:15 +00:00
case "Easy":
return 1;
case "Moderate":
return 2;
case "Challenging":
return 3;
}
}
2021-02-28 15:10:26 +00:00
let dl1 = difficultyLevel(a.difficulty);
let dl2 = difficultyLevel(b.difficulty);
switch (this.sortType) {
2021-04-12 18:09:48 +00:00
case "title":
2021-01-23 17:20:15 +00:00
return titleOrder > 0 ? 1 : titleOrder < 0 ? -1 : 0;
case "Quickest first":
return d1 > d2 ? 1 : d1 < d2 ? -1 : 0;
case "Slowest first":
return d1 > d2 ? -1 : d1 < d2 ? 1 : 0;
case "Rating":
return r1 > r2 ? -1 : r1 < r2 ? 1 : 0;
case "Difficulty level":
return dl1 > dl2 ? 1 : dl1 < dl2 ? -1 : 0;
case "Last updated":
return ld1 < ld2 ? 1 : ld1 > ld2 ? -1 : 0;
case "Newest first":
return cd1 < cd2 ? 1 : cd1 > cd2 ? -1 : 0;
case "Oldest first":
return cd1 < cd2 ? -1 : cd1 > cd2 ? 1 : 0;
}
},
2021-03-21 17:02:04 +00:00
getItemPos(id) {
2021-02-28 15:10:26 +00:00
let length = this.filteredRecipes.length;
2021-04-12 18:09:48 +00:00
let l2 = this.layout == "grid" || this.layout == "photogrid";
2021-04-01 10:55:35 +00:00
let oddOrEven = this.oddOrEven(id);
2021-03-21 17:02:04 +00:00
let itemPos =
id == this.filteredRecipes[0].id ||
(length > 1 && l2 && id == this.filteredRecipes[1].id)
? "firstItem"
: id == this.filteredRecipes[length - 1].id ||
(length > 1 &&
l2 &&
2021-04-01 10:55:35 +00:00
oddOrEven == " odd" &&
2021-03-21 17:02:04 +00:00
id == this.filteredRecipes[length - 2].id)
? "lastItem"
: "";
2021-04-01 10:55:35 +00:00
let selection = this.selection.includes(id) ? "selected" : "unselected";
let classes = itemPos + " " + selection;
return l2 ? classes + oddOrEven : classes;
2021-03-21 17:02:04 +00:00
},
oddOrEven(id) {
return this.filteredRecipes.map((e) => e.id).indexOf(id) % 2 === 0
? " odd"
: " even";
2021-01-23 17:20:15 +00:00
},
2021-04-01 10:55:35 +00:00
getTags(tags) {
return tags.join(" · ");
},
2021-01-23 17:20:15 +00:00
2020-11-10 18:28:48 +00:00
// NAVIGATION HANDLERS
2021-04-01 10:55:35 +00:00
barsVisibility(bool) {
this.showTools = bool;
},
hijackBackEvent() {
2021-02-28 15:10:26 +00:00
AndroidApplication.on(
AndroidApplication.activityBackPressedEvent,
2021-04-01 10:55:35 +00:00
this.backEvent
2021-02-28 15:10:26 +00:00
);
2020-10-21 17:54:45 +00:00
},
2021-04-01 10:55:35 +00:00
releaseBackEvent() {
2021-02-28 15:10:26 +00:00
AndroidApplication.off(
AndroidApplication.activityBackPressedEvent,
2021-04-01 10:55:35 +00:00
this.backEvent
2021-02-28 15:10:26 +00:00
);
2020-10-21 17:54:45 +00:00
},
2021-04-01 10:55:35 +00:00
backEvent(args) {
if (this.showSearch) {
args.cancel = true;
this.closeSearch();
} else if (this.selectMode) {
args.cancel = true;
this.clearSelection();
} else if (
2021-04-12 18:09:48 +00:00
["favourites", "trylater", "Filtered recipes"].includes(
2021-04-01 10:55:35 +00:00
this.currentComponent
)
) {
args.cancel = true;
this.goToHome();
}
},
goToHome() {
this.setComponent("EnRecipes");
this.filterFavourites = this.filterTrylater = null;
this.clearFilter();
},
navigateTo(to, title, page) {
this.showTools = false;
if (page) {
this.$navigateTo(to, {
transition: {
name: "fade",
duration: 250,
curve: "easeOut",
},
});
} else if (title !== this.currentComponent) {
2021-04-12 18:09:48 +00:00
this.setComponent(title);
this.filterFavourites = to == "favourites";
this.filterTrylater = to == "trylater";
2021-04-01 10:55:35 +00:00
this.clearFilter();
}
2020-10-21 17:54:45 +00:00
},
2020-11-10 18:28:48 +00:00
addRecipe() {
2021-04-01 10:55:35 +00:00
this.barsVisibility(false);
2021-02-28 15:10:26 +00:00
this.$navigateTo(EditRecipe, {
2020-11-10 18:28:48 +00:00
props: {
2020-12-29 10:35:19 +00:00
filterFavourites: this.filterFavourites,
filterTrylater: this.filterTrylater,
2021-02-28 15:10:26 +00:00
},
2021-04-01 10:55:35 +00:00
transition: {
name: "fade",
duration: 250,
curve: "easeOut",
},
2021-02-28 15:10:26 +00:00
});
2020-10-21 17:54:45 +00:00
},
2021-02-28 15:10:26 +00:00
viewRecipe(recipeID) {
2021-04-01 10:55:35 +00:00
this.barsVisibility(false);
2021-02-28 15:10:26 +00:00
this.$navigateTo(ViewRecipe, {
2020-11-10 18:28:48 +00:00
props: {
filterTrylater: this.filterTrylater,
2021-02-28 15:10:26 +00:00
recipeID,
2020-11-10 18:28:48 +00:00
},
2021-04-01 10:55:35 +00:00
transition: {
name: "fade",
duration: 250,
curve: "easeOut",
},
2021-02-28 15:10:26 +00:00
});
2020-11-10 18:28:48 +00:00
},
2020-12-29 10:35:19 +00:00
viewRandomRecipe() {
2021-04-01 10:55:35 +00:00
this.showTools = false;
2021-02-28 15:10:26 +00:00
this.$navigateTo(ViewRecipe, {
2020-12-29 10:35:19 +00:00
props: {
2021-03-21 17:02:04 +00:00
filterTrylater: true,
2021-02-28 15:10:26 +00:00
recipeID: this.randomRecipeID(),
2020-12-29 10:35:19 +00:00
},
2021-04-01 10:55:35 +00:00
transition: {
name: "fade",
duration: 250,
curve: "easeOut",
2021-02-28 15:10:26 +00:00
},
});
2021-01-23 17:20:15 +00:00
},
2021-04-12 18:09:48 +00:00
touchSelector({ object, action }, comp, title) {
2021-04-01 10:55:35 +00:00
let selected = this.currentComponent == comp;
object.className = action.match(/down|move/)
? `segment ${selected ? "select" : "fade"}`
: `segment ${selected && "select"}`;
2021-04-12 18:09:48 +00:00
if (action == "up") this.navigateTo(comp, title);
2020-12-29 10:35:19 +00:00
},
2021-04-01 10:55:35 +00:00
touchTool({ object, action }, comp, value) {
object.className = action.match(/down|move/) ? `tool fade` : `tool`;
if (action == "up") this.navigateTo(comp, value, true);
2020-12-29 10:35:19 +00:00
},
2020-09-15 11:10:16 +00:00
},
2021-04-01 10:55:35 +00:00
created() {
this.setTheme(ApplicationSettings.getString("appTheme", "Light"));
this.setLayout(ApplicationSettings.getString("layout", "detailed"));
if (!this.recipes.length) this.initRecipes();
this.initListItems();
if (!this.mealPlans.length) this.initMealPlans();
2021-04-12 18:09:48 +00:00
this.setShake(ApplicationSettings.getBoolean("shakeEnabled", true));
this.setFirstDay(ApplicationSettings.getBoolean("mondayFirst", false));
2021-02-28 15:10:26 +00:00
},
};
2020-09-15 11:10:16 +00:00
</script>