Merge remote-tracking branch 'origin/main' into main
|
@ -6,4 +6,4 @@ Here are some important resources:
|
|||
|
||||
- The [roadmap](https://github.com/vishnuraghavb/EnRecipes/projects/1) will tell you whats the future of EnRecipes. Your feedback and suggestions are very important to make EnRecipes the best. If you have an idea to improve EnRecipes, [do let me know](https://github.com/vishnuraghavb/EnRecipes#having-issues-suggestions-and-feedback). I'm always open to ideas ;)
|
||||
- You can help [translate EnRecipes using Weblate](https://hosted.weblate.org/engage/enrecipes/) into the language of your choice. See [translation instructions](https://github.com/vishnuraghavb/EnRecipes/wiki/Translation-Instructions) in the wiki for more information.
|
||||
- Bugs, suggestions or feedback? You can [create an issue here](https://github.com/vishnuraghavb/EnRecipes/issues) or [join the Telegram group](http://t.me/enrecipes)(quicker replies) or contact me at apps@vishnuraghav.com
|
||||
- Bugs, suggestions or feedback? You can [create an issue here](https://github.com/vishnuraghavb/EnRecipes/issues) or [join the Telegram group](http://t.me/enrecipes) (quicker replies) or contact me at apps@vishnuraghav.com
|
||||
|
|
11
README.md
|
@ -6,7 +6,7 @@
|
|||
<a href="https://www.gnu.org/licenses/gpl-3.0" alt="License: GPLv3"><img src="https://img.shields.io/badge/license-GPL%20v3-blue"></a> <a href="https://github.com/vishnuraghavb/EnRecipes/releases" alt="Release version"><img src="https://img.shields.io/github/v/release/vishnuraghavb/EnRecipes?color=ff5200"/></a> <a href="https://hosted.weblate.org/engage/enrecipes/">
|
||||
<img src="https://hosted.weblate.org/widgets/enrecipes/-/app-translations/svg-badge.svg" alt="Translation status" /></a>
|
||||
<p align="center">
|
||||
<a href="https://play.google.com/store/apps/details?id=com.vishnuraghav.enrecipes"><img src="assets/Images/google-play-badge.png" height="80"/></a><a href="https://apt.izzysoft.de/fdroid/index/apk/com.vishnuraghav.enrecipes"><img src="assets/Images/IzzyOnDroid.png" height="80"/></a><br>You can also get the <a href="https://github.com/vishnuraghavb/EnRecipes/releases/latest">latest release on GitHub</a>
|
||||
<a href="https://play.google.com/store/apps/details?id=com.vishnuraghav.EnRecipes"><img src="assets/Images/google-play-badge.png" height="80"/></a><a href="https://apt.izzysoft.de/fdroid/index/apk/com.vishnuraghav.EnRecipes"><img src="assets/Images/IzzyOnDroid.png" height="80"/></a><br>You can also get the <a href="https://github.com/vishnuraghavb/EnRecipes/releases/latest">latest release on GitHub</a>
|
||||
</p>
|
||||
<h2 align="center">Enjoying EnRecipes?</h2>
|
||||
<p align="center">Please consider making a small donation to help fund the project. Developing an application, especially one that is open source and completely free, takes a lot of time and effort.
|
||||
|
@ -28,16 +28,17 @@
|
|||
- Scale your recipe ingredients to serve more or less people
|
||||
- Get notified of the last time you tried a recipe
|
||||
- Share your recipe to anyone by any means as a nicely formatted message. You can share the recipe photo too.
|
||||
- Shake device to view random recipe
|
||||
- Shake your device to view a random recipe
|
||||
- Create meal plans
|
||||
- Import/Export recipes
|
||||
- Light, Dark and Black themes
|
||||
- Set cooking timers
|
||||
- You can Import or Export your data
|
||||
- Has Light, Dark and Black themes
|
||||
|
||||
## Highlights
|
||||
|
||||
- 100% free and open-source
|
||||
- Private by Design
|
||||
- No permissions required
|
||||
- No special permissions required
|
||||
- No annoying ads or pop-ups
|
||||
|
||||
**Languages being translated**:
|
||||
|
|
195
app/app.scss
|
@ -1,3 +1,4 @@
|
|||
// Colours
|
||||
$gray0: #f8f9fa;
|
||||
$gray1: #f1f3f5;
|
||||
$gray2: #e9ecef;
|
||||
|
@ -11,21 +12,29 @@ $gray9: #212529;
|
|||
$gray10: #000000;
|
||||
$orange: #ff5200;
|
||||
|
||||
// FontSizes based on Minor Third
|
||||
$t1: 25;
|
||||
$t2: 21;
|
||||
$t3: 17;
|
||||
$t4: 14;
|
||||
$t5: 12; // Base size
|
||||
$t6: 10;
|
||||
|
||||
Page {
|
||||
font-family: 'Inter-Medium';
|
||||
font-size: 14;
|
||||
font-family: 'Inter-Medium', sans-serif;
|
||||
font-size: $t4;
|
||||
}
|
||||
.ico {
|
||||
font-family: 'enrecipes';
|
||||
font-size: 24;
|
||||
vertical-alignment: center;
|
||||
&.sm {
|
||||
font-size: 16;
|
||||
font-size: $t3;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
.tb {
|
||||
font-family: 'Inter-Bold';
|
||||
font-family: 'Inter-Bold', sans-serif;
|
||||
}
|
||||
.tac {
|
||||
text-align: center;
|
||||
|
@ -36,7 +45,7 @@ Page {
|
|||
.pageTitle {
|
||||
@extend .tb;
|
||||
@extend .tw;
|
||||
font-size: 25;
|
||||
font-size: $t1;
|
||||
padding: 16 16 24;
|
||||
}
|
||||
.Light {
|
||||
|
@ -60,7 +69,6 @@ Page {
|
|||
background: $gray0;
|
||||
}
|
||||
.fieldLabel,
|
||||
.dayName,
|
||||
.sub {
|
||||
color: $gray6;
|
||||
}
|
||||
|
@ -98,7 +106,6 @@ Page {
|
|||
background: $gray8;
|
||||
}
|
||||
.fieldLabel,
|
||||
.dayName,
|
||||
.sub {
|
||||
color: $gray5;
|
||||
}
|
||||
|
@ -136,7 +143,6 @@ Page {
|
|||
background: $gray9;
|
||||
}
|
||||
.fieldLabel,
|
||||
.dayName,
|
||||
.sub {
|
||||
color: $gray6;
|
||||
}
|
||||
|
@ -169,14 +175,13 @@ TextView {
|
|||
line-height: 4;
|
||||
}
|
||||
#searchBar {
|
||||
padding-left: 0;
|
||||
margin: 0;
|
||||
padding: 13 12;
|
||||
}
|
||||
.inputField {
|
||||
margin-bottom: 24;
|
||||
}
|
||||
.fieldLabel {
|
||||
font-size: 12;
|
||||
font-size: $t5;
|
||||
}
|
||||
.progressContainer {
|
||||
width: 100%;
|
||||
|
@ -198,25 +203,28 @@ button {
|
|||
border-radius: 12;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
&:active {
|
||||
@extend .fade;
|
||||
}
|
||||
&.ico {
|
||||
width: 48;
|
||||
height: 48;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
&:active {
|
||||
@extend .fade;
|
||||
}
|
||||
}
|
||||
&.text {
|
||||
@extend .tb;
|
||||
color: $orange;
|
||||
&:active {
|
||||
@extend .fade;
|
||||
}
|
||||
}
|
||||
&.big {
|
||||
margin-top: 8;
|
||||
padding: 16 0;
|
||||
}
|
||||
&.sm {
|
||||
font-size: 12;
|
||||
font-size: $t5;
|
||||
padding: 12;
|
||||
}
|
||||
&.min {
|
||||
|
@ -224,10 +232,16 @@ button {
|
|||
height: 40;
|
||||
vertical-alignment: center;
|
||||
}
|
||||
&.fb:active {
|
||||
@extend .fade;
|
||||
}
|
||||
&.rate {
|
||||
margin: 0 4 0 0;
|
||||
width: 32;
|
||||
height: 32;
|
||||
&:active {
|
||||
@extend .fade;
|
||||
}
|
||||
}
|
||||
}
|
||||
ActivityIndicator {
|
||||
|
@ -246,14 +260,15 @@ ActivityIndicator {
|
|||
.value {
|
||||
padding: 0 0 0 8;
|
||||
vertical-alignment: center;
|
||||
&.rtl {
|
||||
&.r {
|
||||
padding: 0 8 0 0;
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
}
|
||||
&.select {
|
||||
color: $orange;
|
||||
@extend .hl;
|
||||
}
|
||||
}
|
||||
.select {
|
||||
color: $orange;
|
||||
@extend .hl;
|
||||
}
|
||||
.emptyState {
|
||||
padding: 16 16 8;
|
||||
|
@ -262,7 +277,7 @@ ActivityIndicator {
|
|||
}
|
||||
.title {
|
||||
@extend .tb;
|
||||
font-size: 17;
|
||||
font-size: $t3;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -272,22 +287,18 @@ ActivityIndicator {
|
|||
padding: 8 16;
|
||||
.recipeInfo {
|
||||
vertical-alignment: center;
|
||||
padding: 0 0 4 8;
|
||||
&.rtl {
|
||||
transform: none;
|
||||
padding: 0 8 4 0;
|
||||
}
|
||||
padding: 0 8 4;
|
||||
}
|
||||
.title {
|
||||
padding: 0 0 4;
|
||||
}
|
||||
.attr {
|
||||
font-size: 10;
|
||||
padding: 0 6 1 2;
|
||||
&.rtl {
|
||||
padding: 0 2 1 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
.attrs {
|
||||
orientation: horizontal;
|
||||
}
|
||||
.attr {
|
||||
font-size: $t6;
|
||||
padding: 1 4;
|
||||
}
|
||||
.simple .recipeInfo {
|
||||
padding: 8 0;
|
||||
|
@ -343,20 +354,24 @@ ActivityIndicator {
|
|||
.group-info {
|
||||
padding: 16 16 16 72;
|
||||
line-height: 4;
|
||||
&.r {
|
||||
padding: 16 72 16 16;
|
||||
}
|
||||
}
|
||||
.options {
|
||||
.option {
|
||||
vertical-align: center;
|
||||
padding: 14 12;
|
||||
padding: 14 16;
|
||||
.ico {
|
||||
margin: 0 24 0 12;
|
||||
width: 40;
|
||||
text-align: center;
|
||||
}
|
||||
.info,
|
||||
.sub {
|
||||
.info {
|
||||
padding: 0 16;
|
||||
@extend .tw;
|
||||
}
|
||||
.sub {
|
||||
font-size: 12;
|
||||
font-size: $t5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -371,7 +386,7 @@ ActivityIndicator {
|
|||
horizontal-alignment: center;
|
||||
}
|
||||
.name {
|
||||
font-size: 21;
|
||||
font-size: $t2;
|
||||
}
|
||||
.info {
|
||||
padding: 8 16 24;
|
||||
|
@ -394,9 +409,8 @@ ActivityIndicator {
|
|||
}
|
||||
.attribute {
|
||||
margin: 8 16;
|
||||
.title {
|
||||
margin-right: 8;
|
||||
font-size: 12;
|
||||
.sub {
|
||||
font-size: $t5;
|
||||
}
|
||||
.value {
|
||||
@extend .tb;
|
||||
|
@ -416,7 +430,7 @@ ActivityIndicator {
|
|||
padding: 0 16;
|
||||
.count {
|
||||
@extend .tb;
|
||||
font-size: 17;
|
||||
font-size: $t3;
|
||||
}
|
||||
.value {
|
||||
@extend .tw;
|
||||
|
@ -443,7 +457,7 @@ ActivityIndicator {
|
|||
}
|
||||
.dateInfo {
|
||||
padding: 32 16 16;
|
||||
font-size: 12;
|
||||
font-size: $t5;
|
||||
line-height: 4;
|
||||
}
|
||||
|
||||
|
@ -459,10 +473,12 @@ ActivityIndicator {
|
|||
@extend .tb;
|
||||
@extend .tw;
|
||||
vertical-align: center;
|
||||
margin: 0 12;
|
||||
line-height: 4;
|
||||
}
|
||||
.msg {
|
||||
padding: 14 16;
|
||||
margin: 0;
|
||||
}
|
||||
.fab {
|
||||
margin-left: 8;
|
||||
|
@ -471,21 +487,21 @@ ActivityIndicator {
|
|||
margin: 8 8 0;
|
||||
}
|
||||
}
|
||||
.sidebar {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.toolbar {
|
||||
z-index: 4;
|
||||
padding: 4;
|
||||
margin: 0 0 52;
|
||||
horizontal-alignment: left;
|
||||
.tool {
|
||||
padding: 0 12;
|
||||
padding: 0 8;
|
||||
label {
|
||||
vertical-alignment: center;
|
||||
}
|
||||
.value,
|
||||
.ico {
|
||||
padding: 0 8 0 0;
|
||||
&.rtl {
|
||||
padding: 0 0 0 8;
|
||||
}
|
||||
padding: 0 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -499,7 +515,7 @@ ActivityIndicator {
|
|||
.sectionTitle {
|
||||
@extend .tb;
|
||||
@extend .tw;
|
||||
font-size: 21;
|
||||
font-size: $t2;
|
||||
padding: 0;
|
||||
margin: 32 0 16;
|
||||
}
|
||||
|
@ -509,49 +525,51 @@ ActivityIndicator {
|
|||
margin: 0;
|
||||
}
|
||||
.countdown {
|
||||
font-size: 17;
|
||||
font-size: $t3;
|
||||
color: $orange;
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
// MealPlanner
|
||||
.calendar {
|
||||
padding: 0 8;
|
||||
.navBtn {
|
||||
margin: 0;
|
||||
}
|
||||
.monthName {
|
||||
text-align: center;
|
||||
.monthSwitcher {
|
||||
padding: 0 16;
|
||||
.month {
|
||||
vertical-alignment: center;
|
||||
font-size: 17;
|
||||
}
|
||||
.dayName {
|
||||
margin: 8 0;
|
||||
font-size: 12;
|
||||
text-align: center;
|
||||
}
|
||||
.day {
|
||||
border-radius: 12;
|
||||
}
|
||||
.hasPlans {
|
||||
color: $orange;
|
||||
}
|
||||
.activeDay {
|
||||
@extend .hl;
|
||||
font-size: $t3;
|
||||
}
|
||||
}
|
||||
.dayPlan {
|
||||
padding: 16 16 80;
|
||||
width: 100%;
|
||||
.periodLabel {
|
||||
font-size: 17;
|
||||
text-transform: capitalize;
|
||||
vertical-align: center;
|
||||
.calendar {
|
||||
padding: 0 16;
|
||||
.dayName {
|
||||
vertical-alignment: center;
|
||||
text-align: center;
|
||||
font-size: $t5;
|
||||
}
|
||||
.recipeTitle {
|
||||
@extend .tw;
|
||||
padding: 16 8;
|
||||
line-height: 4;
|
||||
.accent.sub {
|
||||
color: rgba($orange, 0.5);
|
||||
}
|
||||
}
|
||||
.plans {
|
||||
padding: 8 16 80;
|
||||
width: 100%;
|
||||
.date {
|
||||
font-size: $t2;
|
||||
padding: 16 0;
|
||||
}
|
||||
.plan {
|
||||
padding: 8 0;
|
||||
}
|
||||
.meal {
|
||||
font-size: $t3;
|
||||
padding: 8 0;
|
||||
}
|
||||
.planContent {
|
||||
min-height: 48;
|
||||
padding: 8;
|
||||
}
|
||||
.attr {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -566,7 +584,7 @@ ActivityIndicator {
|
|||
@extend .tb;
|
||||
@extend .tw;
|
||||
padding: 16;
|
||||
font-size: 21;
|
||||
font-size: $t2;
|
||||
}
|
||||
.input {
|
||||
padding: 0 16 8;
|
||||
|
@ -581,13 +599,12 @@ ActivityIndicator {
|
|||
margin: 16 0;
|
||||
}
|
||||
.listItem {
|
||||
@extend .tw;
|
||||
letter-spacing: 0;
|
||||
text-transform: none;
|
||||
line-height: 4;
|
||||
padding: 13 16;
|
||||
margin: 0;
|
||||
background: transparent;
|
||||
background-color: transparent;
|
||||
}
|
||||
.shareItem {
|
||||
border-radius: 12;
|
||||
|
@ -649,10 +666,10 @@ ActivityIndicator {
|
|||
|
||||
// -----------------------------
|
||||
// Helpers
|
||||
.rtl {
|
||||
.f {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
.clickable {
|
||||
.accent {
|
||||
color: $orange;
|
||||
}
|
||||
.hal {
|
||||
|
|
|
@ -1,53 +1,55 @@
|
|||
<template>
|
||||
<Page @loaded="onPageLoad" actionBarHidden="true">
|
||||
<Page @loaded="pgLoad" @unloaded="pgUnload" actionBarHidden="true">
|
||||
<GridLayout rows="*, auto" columns="*">
|
||||
<ScrollView
|
||||
@scroll="onScroll($event)"
|
||||
@scroll="svScroll($event)"
|
||||
rowSpan="2"
|
||||
scrollBarIndicatorVisible="false"
|
||||
>
|
||||
<StackLayout>
|
||||
<GridLayout rows="auto" columns="*, auto, 8">
|
||||
<Label class="pageTitle" :text="'timer' | L" />
|
||||
<Button
|
||||
col="1"
|
||||
class="ico"
|
||||
:text="icon.cog"
|
||||
@tap="$navigateTo(CTSettings)"
|
||||
/>
|
||||
</GridLayout>
|
||||
<RGridLayout :rtl="RTL" rows="auto" columns="*, auto, 12">
|
||||
<RLabel class="pageTitle" :text="'timer' | L" />
|
||||
<Button col="1" class="ico" :text="icon.cog" @tap="navigateTo" />
|
||||
</RGridLayout>
|
||||
<Timer
|
||||
v-for="(timer, i) in activeTimers"
|
||||
:key="timer.id"
|
||||
v-for="timer in activeTimers"
|
||||
:key="timer.id + key"
|
||||
:timer="timer"
|
||||
:timerIndex="i"
|
||||
:formattedTime="formattedTime"
|
||||
:removeTimer="removeTimer"
|
||||
:addToPreset="addToPreset"
|
||||
:togglePause="togglePause"
|
||||
:fireTimer="fireTimer"
|
||||
:timerAlert="timerAlert"
|
||||
:showToast="showToast"
|
||||
/>
|
||||
<StackLayout class="listSpace"> </StackLayout>
|
||||
</StackLayout>
|
||||
</ScrollView>
|
||||
<GridLayout
|
||||
<GridLayout v-if="!activeTimers.length" rows="*, auto">
|
||||
<StackLayout row="1" class="emptyState">
|
||||
<RLabel class="title" :text="'ccwt' | L" />
|
||||
<RLabel :text="'plsAdd' | L" />
|
||||
</StackLayout>
|
||||
</GridLayout>
|
||||
<RGridLayout
|
||||
:rtl="RTL"
|
||||
row="1"
|
||||
@loaded="onAppBarLoad"
|
||||
@loaded="abLoad"
|
||||
class="appbar"
|
||||
:hidden="showUndo"
|
||||
columns="auto, *, auto"
|
||||
>
|
||||
<Button class="ico" :text="icon.back" @tap="$navigateBack()" />
|
||||
<Button class="ico rtl" :text="icon.back" @tap="navigateBack" />
|
||||
<Button class="ico fab" :text="icon.plus" @tap="addTimer" col="2" />
|
||||
</GridLayout>
|
||||
</RGridLayout>
|
||||
<SnackBar
|
||||
:hidden="!showUndo || toast"
|
||||
:count="countdown"
|
||||
:msg="snackMsg"
|
||||
:undo="undoDel"
|
||||
:action="hideBar"
|
||||
:onload="sbLoad"
|
||||
/>
|
||||
<Toast :toast="toast" :action="hideBar" />
|
||||
<Toast :onload="tbLoad" :toast="toast" :action="hideBar" />
|
||||
</GridLayout>
|
||||
</Page>
|
||||
</template>
|
||||
|
@ -58,13 +60,17 @@ import {
|
|||
Observable,
|
||||
CoreTypes,
|
||||
Application,
|
||||
ApplicationSettings,
|
||||
AndroidApplication,
|
||||
Utils,
|
||||
Device,
|
||||
Frame,
|
||||
} from "@nativescript/core";
|
||||
import {
|
||||
getNumber,
|
||||
setNumber,
|
||||
remove,
|
||||
} from "@nativescript/core/application-settings";
|
||||
import { mapState, mapActions } from "vuex";
|
||||
|
||||
import EnRecipes from "./EnRecipes.vue";
|
||||
import Action from "./modals/Action.vue";
|
||||
import CTSettings from "./settings/CTSettings.vue";
|
||||
import TimePickerHMS from "./modals/TimePickerHMS.vue";
|
||||
|
@ -72,13 +78,10 @@ import TimerReminder from "./modals/TimerReminder.vue";
|
|||
import Timer from "./sub/Timer.vue";
|
||||
import Toast from "./sub/Toast.vue";
|
||||
import SnackBar from "./sub/SnackBar.vue";
|
||||
|
||||
import * as utils from "~/shared/utils";
|
||||
import { EventBus } from "~/main";
|
||||
let undoTimer,
|
||||
firingTimers = [];
|
||||
declare const com: any;
|
||||
|
||||
import { EvtBus } from "~/main";
|
||||
let barTimer;
|
||||
declare const com, android: any;
|
||||
export default {
|
||||
components: { Timer, Toast, SnackBar },
|
||||
props: ["recipeID"],
|
||||
|
@ -86,43 +89,62 @@ export default {
|
|||
return {
|
||||
scrollPos: 1,
|
||||
appbar: null,
|
||||
toastbar: null,
|
||||
snackbar: null,
|
||||
scrollView: null,
|
||||
countdown: 5,
|
||||
snackMsg: null,
|
||||
showUndo: false,
|
||||
undo: false,
|
||||
CTSettings: CTSettings,
|
||||
showUndo: 0,
|
||||
undo: 0,
|
||||
toast: null,
|
||||
key: 99,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState([
|
||||
"icon",
|
||||
"recipes",
|
||||
"currentComponent",
|
||||
"timerSound",
|
||||
"timerVibrate",
|
||||
"timerDelay",
|
||||
"timerPresets",
|
||||
"activeTimers",
|
||||
"FGService",
|
||||
"RTL",
|
||||
]),
|
||||
hasBackStack() {
|
||||
return Frame.topmost().backStack.length;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions([
|
||||
"setComponent",
|
||||
"addActiveTimer",
|
||||
"removeActiveTimer",
|
||||
"clearTimerInterval",
|
||||
"addTimerPreset",
|
||||
"updateActiveTimer",
|
||||
"setFGService",
|
||||
]),
|
||||
onPageLoad({ object }) {
|
||||
pgLoad({ object }) {
|
||||
object.bindingContext = new Observable();
|
||||
this.setComponent("CookingTimer");
|
||||
if (this.activeTimers.filter((e: any) => e.done).length)
|
||||
this.openReminder();
|
||||
this.keepScreenOnCountUp();
|
||||
setNumber("isTimer", 1);
|
||||
},
|
||||
onAppBarLoad({ object }) {
|
||||
pgUnload() {
|
||||
utils.keepScreenOn(0);
|
||||
},
|
||||
abLoad({ object }) {
|
||||
this.appbar = object;
|
||||
},
|
||||
onScroll(args) {
|
||||
tbLoad({ object }) {
|
||||
this.toastbar = object;
|
||||
},
|
||||
sbLoad({ object }) {
|
||||
this.snackbar = object;
|
||||
},
|
||||
svScroll(args) {
|
||||
this.scrollView = args.object;
|
||||
let scrollUp;
|
||||
let y = args.scrollY;
|
||||
if (y) {
|
||||
|
@ -132,18 +154,19 @@ export default {
|
|||
if (!scrollUp && ab == 0) {
|
||||
this.appbar.animate({
|
||||
translate: { x: 0, y: 64 },
|
||||
duration: 250,
|
||||
duration: 200,
|
||||
curve: CoreTypes.AnimationCurve.ease,
|
||||
});
|
||||
} else if (scrollUp && ab == 64) {
|
||||
this.appbar.animate({
|
||||
translate: { x: 0, y: 0 },
|
||||
duration: 250,
|
||||
duration: 200,
|
||||
curve: CoreTypes.AnimationCurve.ease,
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// HELPERS
|
||||
getRecipeTitle(id) {
|
||||
let recipe = this.recipes.filter((e) => e.id === id)[0];
|
||||
|
@ -168,81 +191,111 @@ export default {
|
|||
},
|
||||
|
||||
// NOTIFICATION HANDLERS
|
||||
notifyTimers() {
|
||||
timerInfo() {
|
||||
let activeCount = this.activeTimers.length;
|
||||
let pausedCount = this.activeTimers.filter((e) => e.isPaused).length;
|
||||
let ongoingCount = activeCount - pausedCount;
|
||||
console.log("notifying");
|
||||
utils.TimerNotif.show({
|
||||
bID: "bringToFront",
|
||||
cID: "cti",
|
||||
cName: "Cooking Timer info",
|
||||
description: `${ongoingCount} ongoing, ${pausedCount} paused`,
|
||||
nID: 777,
|
||||
priority: -2,
|
||||
sound: null,
|
||||
title: localize("timer"),
|
||||
});
|
||||
if (activeCount <= 0) this.foregroundService(false);
|
||||
this.foregroundService(activeCount);
|
||||
function show() {
|
||||
utils.TimerNotif.show({
|
||||
bID: "info",
|
||||
cID: "cti",
|
||||
cName: "Cooking Timer info",
|
||||
description: localize("oAP", ongoingCount + "", pausedCount),
|
||||
nID: 6,
|
||||
priority: -2,
|
||||
sound: null,
|
||||
title: localize("timer"),
|
||||
});
|
||||
}
|
||||
if (this.FGService)
|
||||
setTimeout(() => this.activeTimers.length && show(), 250);
|
||||
this.keepScreenOnCountUp();
|
||||
utils.wakeLock(ongoingCount);
|
||||
},
|
||||
fireTimer(timer) {
|
||||
console.log("firing");
|
||||
let description = timer.recipeID
|
||||
? " - " + this.getRecipeTitle(timer.recipeID)
|
||||
: "";
|
||||
let title = timer.label;
|
||||
let time = this.formattedTime(timer.time);
|
||||
let bID = "timer" + timer.id;
|
||||
timerAlert() {
|
||||
let title, description, bID;
|
||||
let firedTimers = this.activeTimers.filter((e) => e.done);
|
||||
let timer = firedTimers[0];
|
||||
if (firedTimers.length > 1) {
|
||||
title = localize("texp", firedTimers.length);
|
||||
description = localize("ttv");
|
||||
bID = "alerts";
|
||||
} else if (firedTimers.length == 1) {
|
||||
title =
|
||||
timer.label +
|
||||
(timer.recipeID ? " - " + this.getRecipeTitle(timer.recipeID) : "");
|
||||
description = this.formattedTime(timer.time);
|
||||
bID = "timer" + timer.id;
|
||||
} else {
|
||||
utils.TimerNotif.clear(7);
|
||||
return;
|
||||
}
|
||||
utils.TimerNotif.show({
|
||||
actions: true,
|
||||
actions: 1,
|
||||
bID,
|
||||
cID: "cta",
|
||||
cName: "Cooking Timer alerts",
|
||||
description: time,
|
||||
nID: timer.id,
|
||||
description,
|
||||
multi: firedTimers.length > 1,
|
||||
nID: 7,
|
||||
priority: 1,
|
||||
sound: this.timerSound.uri,
|
||||
title: title + description,
|
||||
title,
|
||||
vibrate: this.timerVibrate,
|
||||
});
|
||||
Application.android.registerBroadcastReceiver(bID, (ctx, intent) => {
|
||||
let action = intent.getStringExtra("action");
|
||||
console.log(action, "firing");
|
||||
EventBus.$emit(bID, action);
|
||||
if (firedTimers.length == 1) {
|
||||
Application.android.registerBroadcastReceiver(bID, (ctx, intent) => {
|
||||
EvtBus.$emit(bID, intent.getStringExtra("action"));
|
||||
Application.android.unregisterBroadcastReceiver(bID);
|
||||
});
|
||||
} else {
|
||||
Application.android.unregisterBroadcastReceiver(bID);
|
||||
Application.android.registerBroadcastReceiver(bID, (ctx, intent) => {
|
||||
if (intent.getStringExtra("action") == "dismissAll") {
|
||||
firedTimers.forEach((t) => this.removeTimer(t.id, 1));
|
||||
Application.android.unregisterBroadcastReceiver(bID);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
openReminder() {
|
||||
this.clearTimerInterval();
|
||||
this.$showModal(TimerReminder, {
|
||||
fullscreen: true,
|
||||
props: {
|
||||
formattedTime: this.formattedTime,
|
||||
removeTimer: this.removeTimer,
|
||||
togglePause: this.togglePause,
|
||||
timerAlert: this.timerAlert,
|
||||
showToast: this.showToast,
|
||||
},
|
||||
}).then(() => {
|
||||
this.clearTimerInterval();
|
||||
this.key = Math.floor(Math.random() * 900) + 100;
|
||||
});
|
||||
firingTimers.push(timer);
|
||||
// if (firingTimers.length == 1) {
|
||||
// this.$showModal(TimerReminder, {
|
||||
// fullscreen: true,
|
||||
// props: {
|
||||
// timers: firingTimers,
|
||||
// stop: this.stopFiringTimers,
|
||||
// formattedTime: this.formattedTime,
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
},
|
||||
stopFiringTimers() {
|
||||
firingTimers.forEach((e) => utils.TimerNotif.clear(e.id));
|
||||
firingTimers = [];
|
||||
},
|
||||
openReminder() {},
|
||||
foregroundService(bool) {
|
||||
foregroundService(n) {
|
||||
const ctx = Utils.ad.getApplicationContext();
|
||||
const intent = new android.content.Intent(
|
||||
ctx,
|
||||
com.tns.ForegroundService.class
|
||||
);
|
||||
if (bool)
|
||||
if (n && !this.FGService) {
|
||||
parseInt(Device.sdkVersion) < 26
|
||||
? ctx.startService(intent)
|
||||
: ctx.startForegroundService(intent);
|
||||
else ctx.stopService(intent);
|
||||
this.setFGService(1);
|
||||
setNumber("FGService", 1);
|
||||
} else if (!this.activeTimers.length) {
|
||||
ctx.stopService(intent);
|
||||
this.setFGService(0);
|
||||
setNumber("FGService", 0);
|
||||
}
|
||||
},
|
||||
|
||||
// DATA HANDLERS
|
||||
addTimer() {
|
||||
this.foregroundService(true);
|
||||
this.$showModal(TimePickerHMS, {
|
||||
props: {
|
||||
title: "ntmr",
|
||||
|
@ -258,7 +311,7 @@ export default {
|
|||
);
|
||||
this.$showModal(Action, {
|
||||
props: {
|
||||
title: "tmrPrsts",
|
||||
title: "prsts",
|
||||
list,
|
||||
},
|
||||
}).then((preset) => {
|
||||
|
@ -266,128 +319,155 @@ export default {
|
|||
let timer = JSON.parse(
|
||||
JSON.stringify(this.timerPresets[list.indexOf(preset)])
|
||||
);
|
||||
timer.id = this.getRandomID();
|
||||
timer.id = utils.getRandomID(1);
|
||||
timer.recipeID = this.recipeID;
|
||||
timer.timerInt = timer.isPaused = 0;
|
||||
timer.preset = timer.mode = 1;
|
||||
this.addActiveTimer({
|
||||
timer,
|
||||
index: this.activeTimers.length,
|
||||
i: this.activeTimers.length,
|
||||
});
|
||||
this.notifyTimers();
|
||||
this.timerInfo();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (res.time != "00:00:00") {
|
||||
this.addActiveTimer({
|
||||
timer: {
|
||||
id: this.getRandomID(),
|
||||
label: res.label,
|
||||
recipeID: this.recipeID,
|
||||
time: res.time,
|
||||
timerInterval: null,
|
||||
isPaused: false,
|
||||
preset: 0,
|
||||
},
|
||||
index: this.activeTimers.length,
|
||||
});
|
||||
this.notifyTimers();
|
||||
}
|
||||
let mode = res.time != "00:00:00" ? 1 : 0;
|
||||
this.addActiveTimer({
|
||||
timer: {
|
||||
id: utils.getRandomID(1),
|
||||
label: res.label,
|
||||
recipeID: this.recipeID,
|
||||
time: res.time,
|
||||
timerInt: 0,
|
||||
isPaused: 0,
|
||||
preset: 0,
|
||||
done: 0,
|
||||
mode,
|
||||
},
|
||||
i: this.activeTimers.length,
|
||||
});
|
||||
this.timerInfo();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
removeTimer(id, index, noUndo) {
|
||||
let temp = this.activeTimers[index];
|
||||
this.removeActiveTimer(index);
|
||||
utils.TimerNotif.clear(id);
|
||||
if (!noUndo) {
|
||||
this.showUndoBar("tmrClr")
|
||||
.then(() => {
|
||||
this.foregroundService(true);
|
||||
this.addActiveTimer({
|
||||
timer: temp,
|
||||
index,
|
||||
});
|
||||
this.notifyTimers();
|
||||
})
|
||||
.catch(() => {
|
||||
ApplicationSettings.remove(`${temp.id}progress`);
|
||||
});
|
||||
removeTimer(id, noUndo) {
|
||||
let i = this.activeTimers.findIndex((e) => e.id == id);
|
||||
let temp = this.activeTimers[i];
|
||||
clearInterval(temp.timerInt);
|
||||
temp.timerInt = 0;
|
||||
this.removeActiveTimer(i);
|
||||
let secs = [getNumber(`${temp.id}c`, 0), getNumber(`${temp.id}d`, 0)];
|
||||
function removeSettings() {
|
||||
remove(`${temp.id}c`);
|
||||
remove(`${temp.id}d`);
|
||||
}
|
||||
this.notifyTimers();
|
||||
removeSettings();
|
||||
if (!noUndo) {
|
||||
this.showUndoBar("tmrRm")
|
||||
.then(() => {
|
||||
setNumber(`${temp.id}c`, secs[0]),
|
||||
setNumber(`${temp.id}d`, secs[1]),
|
||||
this.addActiveTimer({
|
||||
timer: temp,
|
||||
i,
|
||||
});
|
||||
this.timerInfo();
|
||||
})
|
||||
.catch(() => removeSettings());
|
||||
}
|
||||
this.timerAlert();
|
||||
this.timerInfo();
|
||||
},
|
||||
addToPreset(timer) {
|
||||
timer = JSON.parse(JSON.stringify(timer));
|
||||
timer.recipeID = timer.timerInterval = null;
|
||||
timer.preset = 1;
|
||||
this.addTimerPreset(timer);
|
||||
this.showToast("aTPrst");
|
||||
},
|
||||
togglePause(timer, bool) {
|
||||
if (typeof bool === "boolean") timer.isPaused = bool;
|
||||
else timer.isPaused = !timer.isPaused;
|
||||
togglePause(timer, n) {
|
||||
timer.isPaused =
|
||||
typeof n === "number" ? n : (!timer.isPaused as boolean | 0);
|
||||
this.updateActiveTimer(timer);
|
||||
this.notifyTimers();
|
||||
n ? 0 : this.timerInfo();
|
||||
},
|
||||
showToast(data) {
|
||||
this.toast = localize(data);
|
||||
utils.timer(5, (val) => {
|
||||
if (!val) this.toast = val;
|
||||
this.animateBar(this.snackbar, 0);
|
||||
this.animateBar(this.appbar, 0).then(() => {
|
||||
this.showUndo = 0;
|
||||
this.toast = localize(data);
|
||||
this.animateBar(this.toastbar, 1);
|
||||
let a = 5;
|
||||
clearInterval(barTimer);
|
||||
barTimer = setInterval(() => a-- < 1 && this.hideBar(), 1000);
|
||||
});
|
||||
},
|
||||
showUndoBar(message) {
|
||||
return new Promise((resolve, reject) => {
|
||||
clearTimeout(undoTimer);
|
||||
this.showUndo = true;
|
||||
this.snackMsg = message;
|
||||
this.countdown = 5;
|
||||
let a = 5;
|
||||
undoTimer = setInterval(() => {
|
||||
if (this.undo) {
|
||||
this.showUndo = this.undo = false;
|
||||
clearTimeout(undoTimer);
|
||||
resolve(true);
|
||||
}
|
||||
this.countdown = Math.round((a -= 0.1));
|
||||
if (this.countdown < 1) {
|
||||
this.showUndo = false;
|
||||
clearTimeout(undoTimer);
|
||||
reject(true);
|
||||
}
|
||||
}, 100);
|
||||
this.animateBar(this.toastbar, 0);
|
||||
this.animateBar(this.appbar, 0).then(() => {
|
||||
this.toast = null;
|
||||
this.showUndo = 1;
|
||||
this.snackMsg = message;
|
||||
this.countdown = 5;
|
||||
this.animateBar(this.snackbar, 1).then(() => {
|
||||
let a = 5;
|
||||
clearInterval(barTimer);
|
||||
barTimer = setInterval(() => {
|
||||
if (this.undo) {
|
||||
this.hideBar();
|
||||
resolve(1);
|
||||
}
|
||||
this.countdown = Math.round((a -= 0.1));
|
||||
if (this.countdown < 1) {
|
||||
this.hideBar();
|
||||
reject(1);
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
hideBar({ object }) {
|
||||
this.appbar.translateY = 64;
|
||||
object
|
||||
.animate({
|
||||
opacity: 0,
|
||||
translate: { x: 0, y: 64 },
|
||||
duration: 250,
|
||||
curve: CoreTypes.AnimationCurve.ease,
|
||||
})
|
||||
.then(() => {
|
||||
this.showUndo = false;
|
||||
hideBar() {
|
||||
clearInterval(barTimer);
|
||||
this.animateBar(this.toast ? this.toastbar : this.snackbar, 0).then(
|
||||
() => {
|
||||
this.showUndo = this.undo = 0;
|
||||
this.toast = null;
|
||||
this.appbar.animate({
|
||||
translate: { x: 0, y: 0 },
|
||||
duration: 250,
|
||||
curve: CoreTypes.AnimationCurve.ease,
|
||||
});
|
||||
object.opacity = 1;
|
||||
object.translateY = 0;
|
||||
clearTimeout(undoTimer);
|
||||
});
|
||||
this.animateBar(this.appbar, 1);
|
||||
}
|
||||
);
|
||||
},
|
||||
undoDel() {
|
||||
this.undo = true;
|
||||
this.undo = 1;
|
||||
},
|
||||
|
||||
//NAVIGATION HANDLERS
|
||||
navigateTo() {
|
||||
this.$navigateTo(CTSettings, {
|
||||
transition: {
|
||||
name: this.RTL ? "slideRight" : "slide",
|
||||
duration: 200,
|
||||
curve: "easeOut",
|
||||
},
|
||||
});
|
||||
},
|
||||
navigateBack() {
|
||||
setNumber("isTimer", 0);
|
||||
this.hasBackStack
|
||||
? this.$navigateBack()
|
||||
: this.$navigateTo(EnRecipes, {
|
||||
clearHistory: true,
|
||||
});
|
||||
},
|
||||
|
||||
// HELPERS
|
||||
getRandomID() {
|
||||
return Math.floor(Math.random() * 9000000000) + 1000000000;
|
||||
keepScreenOnCountUp() {
|
||||
utils.keepScreenOn(
|
||||
this.activeTimers.filter((e: any) => !e.isPaused).length
|
||||
);
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.clearTimerInterval();
|
||||
this.recipeID && this.addTimer();
|
||||
},
|
||||
destroyed() {
|
||||
setNumber("isTimer", 0);
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
<template>
|
||||
<Page @loaded="onPageLoad" @unloaded="onPageUnload" actionBarHidden="true">
|
||||
<GridLayout rows="*, auto" columns="auto, *">
|
||||
<ScrollView
|
||||
rowSpan="2"
|
||||
colSpan="2"
|
||||
@scroll="!showUndo && onScroll($event)"
|
||||
>
|
||||
<Page @loaded="pgLoad" @unloaded="onPageUnload" actionBarHidden="true">
|
||||
<GridLayout rows="*, auto" columns="auto, *, auto">
|
||||
<ScrollView rowSpan="2" colSpan="3" @scroll="!showUndo && svLoad($event)">
|
||||
<StackLayout padding="0 16 72">
|
||||
<Label class="pageTitle" padding="16 0" :text="`${title}` | L" />
|
||||
<RLabel class="pageTitle" padding="16 0 24" :text="`${title}` | L" />
|
||||
<Image
|
||||
margin="8 0 32"
|
||||
margin="0 0 32"
|
||||
v-if="recipe.image"
|
||||
:src="recipe.image"
|
||||
stretch="aspectFit"
|
||||
|
@ -20,7 +16,7 @@
|
|||
/>
|
||||
<Button
|
||||
v-else
|
||||
margin="8 0 32"
|
||||
margin="0 0 32"
|
||||
class="ico imgHolder"
|
||||
fontSize="128"
|
||||
:width="screenWidth - 32"
|
||||
|
@ -37,30 +33,33 @@
|
|||
@loaded="setInputTypeText($event, 'words')"
|
||||
/>
|
||||
</StackLayout>
|
||||
<GridLayout columns="*, 8, *">
|
||||
<RGridLayout :rtl="RTL" class="" columns="*, 8, *">
|
||||
<StackLayout class="inputField">
|
||||
<Label class="fieldLabel" :text="'cui' | L" />
|
||||
<TextField
|
||||
@loaded="setGravity"
|
||||
:text="recipe.cuisine | L"
|
||||
editable="false"
|
||||
@focus="!modalOpen && showCuisine(true)"
|
||||
@tap="showCuisine(false)"
|
||||
@focus="!modalOpen && showCuisine(1)"
|
||||
@tap="showCuisine(0)"
|
||||
/>
|
||||
</StackLayout>
|
||||
<StackLayout class="inputField" col="2">
|
||||
<Label class="fieldLabel" :text="'cat' | L" />
|
||||
<TextField
|
||||
@loaded="setGravity"
|
||||
ref="category"
|
||||
:text="recipe.category | L"
|
||||
editable="false"
|
||||
@focus="!modalOpen && showCategories(true)"
|
||||
@tap="showCategories(false)"
|
||||
@focus="!modalOpen && showCategories(1)"
|
||||
@tap="showCategories(0)"
|
||||
/>
|
||||
</StackLayout>
|
||||
</GridLayout>
|
||||
</RGridLayout>
|
||||
<StackLayout class="inputField">
|
||||
<Label class="fieldLabel" :text="'ts' | L" />
|
||||
<TextField
|
||||
@loaded="setGravity"
|
||||
:hint="'tsInfo' | L"
|
||||
autocapitalizationType="words"
|
||||
ref="tags"
|
||||
|
@ -69,31 +68,34 @@
|
|||
returnKeyType="next"
|
||||
/>
|
||||
</StackLayout>
|
||||
<GridLayout columns="*, 8, *">
|
||||
<RGridLayout :rtl="RTL" columns="*, 8, *">
|
||||
<StackLayout class="inputField">
|
||||
<Label class="fieldLabel" :text="'prepT' | L" />
|
||||
<TextField
|
||||
@loaded="setGravity"
|
||||
:text="timeRequired('prepTime')"
|
||||
editable="false"
|
||||
@focus="!modalOpen && setTimeRequired(true, 'prepTime')"
|
||||
@tap="setTimeRequired(false, 'prepTime')"
|
||||
@focus="!modalOpen && setTimeRequired(1, 'prepTime')"
|
||||
@tap="setTimeRequired(0, 'prepTime')"
|
||||
/>
|
||||
</StackLayout>
|
||||
<StackLayout class="inputField" col="2">
|
||||
<Label class="fieldLabel" :text="'cookT' | L" />
|
||||
<TextField
|
||||
@loaded="setGravity"
|
||||
ref="cookTime"
|
||||
:text="timeRequired('cookTime')"
|
||||
editable="false"
|
||||
@focus="!modalOpen && setTimeRequired(true, 'cookTime')"
|
||||
@tap="setTimeRequired(false, 'cookTime')"
|
||||
@focus="!modalOpen && setTimeRequired(1, 'cookTime')"
|
||||
@tap="setTimeRequired(0, 'cookTime')"
|
||||
/>
|
||||
</StackLayout>
|
||||
</GridLayout>
|
||||
<GridLayout columns="*, 8, *">
|
||||
</RGridLayout>
|
||||
<RGridLayout :rtl="RTL" columns="*, 8, *">
|
||||
<StackLayout class="inputField">
|
||||
<Label class="fieldLabel" :text="'yieldQ' | L" />
|
||||
<TextField
|
||||
@loaded="setGravity"
|
||||
ref="yieldQuantity"
|
||||
v-model="recipe.yieldQuantity"
|
||||
hint="1"
|
||||
|
@ -104,22 +106,24 @@
|
|||
<StackLayout class="inputField" col="2">
|
||||
<Label class="fieldLabel" :text="'yieldU' | L" />
|
||||
<TextField
|
||||
@loaded="setGravity"
|
||||
:text="`${recipe.yieldUnit}` | L"
|
||||
editable="false"
|
||||
@focus="!modalOpen && showYieldUnits(true)"
|
||||
@tap="showYieldUnits(false)"
|
||||
@focus="!modalOpen && showYieldUnits(1)"
|
||||
@tap="showYieldUnits(0)"
|
||||
/>
|
||||
</StackLayout>
|
||||
</GridLayout>
|
||||
</RGridLayout>
|
||||
<GridLayout columns="*, 8, *">
|
||||
<StackLayout class="inputField">
|
||||
<StackLayout class="inputField" :col="RTL ? 2 : 0">
|
||||
<Label class="fieldLabel" :text="'Difficulty level' | L" />
|
||||
<TextField
|
||||
@loaded="setGravity"
|
||||
ref="difficultyLevel"
|
||||
:text="`${recipe.difficulty}` | L"
|
||||
editable="false"
|
||||
@focus="!modalOpen && showDifficultyLevel(true)"
|
||||
@tap="showDifficultyLevel(false)"
|
||||
@focus="!modalOpen && showDifficultyLevel(1)"
|
||||
@tap="showDifficultyLevel(0)"
|
||||
/>
|
||||
</StackLayout>
|
||||
</GridLayout>
|
||||
|
@ -128,7 +132,8 @@
|
|||
:text="getTitleCount('ings', 'ingredients')"
|
||||
class="sectionTitle"
|
||||
/>
|
||||
<GridLayout
|
||||
<RGridLayout
|
||||
:rtl="RTL"
|
||||
columns="auto,8,auto,8,*,auto"
|
||||
v-for="(ingredient, index) in recipe.ingredients"
|
||||
:key="'ing' + index"
|
||||
|
@ -147,8 +152,8 @@
|
|||
col="2"
|
||||
:text="`${recipe.ingredients[index].unit}` | L"
|
||||
editable="false"
|
||||
@focus="!modalOpen && showUnits($event, true, index)"
|
||||
@tap="showUnits($event, false, index)"
|
||||
@focus="!modalOpen && showUnits($event, 1, index)"
|
||||
@tap="showUnits($event, 0, index)"
|
||||
/>
|
||||
|
||||
<TextField
|
||||
|
@ -163,13 +168,14 @@
|
|||
/>
|
||||
<Button
|
||||
col="5"
|
||||
class="ico x"
|
||||
class="ico min"
|
||||
:text="icon.x"
|
||||
@tap="removeIngredient(index)"
|
||||
/>
|
||||
</GridLayout>
|
||||
</RGridLayout>
|
||||
<Button
|
||||
class="text big"
|
||||
class="text big hal"
|
||||
:class="{ r: RTL }"
|
||||
:text="'aIngBtn' | L"
|
||||
@tap="addIngredient()"
|
||||
/>
|
||||
|
@ -178,7 +184,8 @@
|
|||
:text="getTitleCount('inss', 'instructions')"
|
||||
class="sectionTitle"
|
||||
/>
|
||||
<GridLayout
|
||||
<RGridLayout
|
||||
:rtl="RTL"
|
||||
columns="*,auto"
|
||||
v-for="(instruction, index) in recipe.instructions"
|
||||
:key="'ins' + index"
|
||||
|
@ -190,13 +197,14 @@
|
|||
/>
|
||||
<Button
|
||||
col="1"
|
||||
class="ico x"
|
||||
class="ico min"
|
||||
:text="icon.x"
|
||||
@tap="removeInstruction(index)"
|
||||
/>
|
||||
</GridLayout>
|
||||
</RGridLayout>
|
||||
<Button
|
||||
class="text big"
|
||||
class="text big hal"
|
||||
:class="{ r: RTL }"
|
||||
:text="'aStpBtn' | L"
|
||||
@tap="addInstruction"
|
||||
/>
|
||||
|
@ -205,32 +213,36 @@
|
|||
:text="getTitleCount('cmbs', 'combinations')"
|
||||
class="sectionTitle"
|
||||
/>
|
||||
<GridLayout
|
||||
<RGridLayout
|
||||
:rtl="RTL"
|
||||
columns="*,auto"
|
||||
v-for="(combination, index) in recipe.combinations"
|
||||
:key="'cmbs' + index"
|
||||
>
|
||||
<TextField
|
||||
@loaded="setGravity"
|
||||
class="combField"
|
||||
:text="getCombinationTitle(combination)"
|
||||
editable="false"
|
||||
/>
|
||||
<Button
|
||||
col="1"
|
||||
class="ico x"
|
||||
class="ico min"
|
||||
:text="icon.x"
|
||||
@tap="removeCombination(combination)"
|
||||
/>
|
||||
</GridLayout>
|
||||
</RGridLayout>
|
||||
<Button
|
||||
class="text big"
|
||||
class="text big hal"
|
||||
:class="{ r: RTL }"
|
||||
:text="'addCmbBtn' | L"
|
||||
@tap="showCombinations"
|
||||
/>
|
||||
<!-- NOTES -->
|
||||
<Label :text="getTitleCount('nos', 'notes')" class="sectionTitle" />
|
||||
<GridLayout
|
||||
columns="*,auto"
|
||||
<RGridLayout
|
||||
:rtl="RTL"
|
||||
columns="*, auto"
|
||||
v-for="(note, index) in recipe.notes"
|
||||
:key="'nos' + index"
|
||||
>
|
||||
|
@ -241,52 +253,53 @@
|
|||
/>
|
||||
<Button
|
||||
col="1"
|
||||
class="ico x"
|
||||
class="ico min"
|
||||
:text="icon.x"
|
||||
@tap="removeNote(index)"
|
||||
/>
|
||||
</GridLayout>
|
||||
<Button class="text big" :text="'aNoBtn' | L" @tap="addNote" />
|
||||
</RGridLayout>
|
||||
<Button
|
||||
class="text big hal"
|
||||
:class="{ r: RTL }"
|
||||
:text="'aNoBtn' | L"
|
||||
@tap="addNote"
|
||||
/>
|
||||
</StackLayout>
|
||||
</ScrollView>
|
||||
<GridLayout
|
||||
<RGridLayout
|
||||
:rtl="RTL && hasChanges"
|
||||
row="1"
|
||||
@loaded="onAppBarLoad"
|
||||
@loaded="abLoad"
|
||||
:hidden="showUndo"
|
||||
class="appbar"
|
||||
:colSpan="hasChanges ? 2 : 1"
|
||||
:col="RTL ? (hasChanges ? 0 : 2) : 0"
|
||||
:colSpan="hasChanges ? 3 : 1"
|
||||
columns="auto, *, auto"
|
||||
>
|
||||
<Button class="ico" :text="icon.back" @tap="navigateBack" />
|
||||
<Button
|
||||
class="ico"
|
||||
:class="{ f: RTL }"
|
||||
:text="icon.back"
|
||||
@tap="navigateBack(0)"
|
||||
/>
|
||||
<Button
|
||||
v-if="hasChanges && !saving"
|
||||
class="ico fab"
|
||||
:text="icon.save"
|
||||
col="2"
|
||||
@tap="saveOperation()"
|
||||
@tap="saveOperation"
|
||||
/>
|
||||
<ActivityIndicator col="2" v-if="saving" :busy="saving" />
|
||||
</GridLayout>
|
||||
</RGridLayout>
|
||||
<SnackBar
|
||||
:hidden="!showUndo"
|
||||
colSpan="2"
|
||||
:count="countdown"
|
||||
:msg="snackMsg"
|
||||
:undo="undoDel"
|
||||
:action="hideUndoBar"
|
||||
:action="hideBar"
|
||||
:onload="sbLoad"
|
||||
/>
|
||||
<!-- <GridLayout
|
||||
row="1"
|
||||
class="appbar snackBar"
|
||||
:hidden="!showUndo"
|
||||
colSpan="2"
|
||||
columns="auto, *, auto"
|
||||
@swipe="hideUndoBar"
|
||||
>
|
||||
<Button :text="countdown" class="ico countdown tb" />
|
||||
<Label class="title" col="1" :text="snackMsg | L" />
|
||||
<Button class="ico fab" :text="icon.undo" @tap="undoDel" col="3" />
|
||||
</GridLayout> -->
|
||||
</GridLayout>
|
||||
</Page>
|
||||
</template>
|
||||
|
@ -294,7 +307,6 @@
|
|||
<script>
|
||||
import {
|
||||
AndroidApplication,
|
||||
ApplicationSettings,
|
||||
File,
|
||||
getFileAccess,
|
||||
ImageSource,
|
||||
|
@ -304,10 +316,15 @@ import {
|
|||
Utils,
|
||||
Observable,
|
||||
CoreTypes,
|
||||
Frame,
|
||||
Application,
|
||||
GridLayout,
|
||||
} from "@nativescript/core";
|
||||
import { getString, setString } from "@nativescript/core/application-settings";
|
||||
import { localize } from "@nativescript/localize";
|
||||
import { ImageCropper } from "nativescript-imagecropper";
|
||||
import { mapState, mapActions } from "vuex";
|
||||
import EnRecipes from "./EnRecipes.vue";
|
||||
import Action from "./modals/Action";
|
||||
import ActionWithSearch from "./modals/ActionWithSearch";
|
||||
import Confirm from "./modals/Confirm";
|
||||
|
@ -315,22 +332,17 @@ import Prompt from "./modals/Prompt";
|
|||
import TimePickerHM from "./modals/TimePickerHM";
|
||||
import * as utils from "~/shared/utils";
|
||||
import SnackBar from "./sub/SnackBar";
|
||||
let undoTimer;
|
||||
let barTimer;
|
||||
export default {
|
||||
components: {
|
||||
SnackBar,
|
||||
},
|
||||
props: [
|
||||
"recipeID",
|
||||
"filterFavourites",
|
||||
"filterTrylater",
|
||||
"navigationFromView",
|
||||
],
|
||||
props: ["recipeID", "filterFavourites", "filterTrylater", "dupRecipe"],
|
||||
data() {
|
||||
return {
|
||||
title: "newRec",
|
||||
recipe: {
|
||||
id: this.recipeID ? this.recipeID : this.getRandomID(),
|
||||
id: this.recipeID || utils.getRandomID(0),
|
||||
image: null,
|
||||
title: null,
|
||||
cuisine: "Undefined",
|
||||
|
@ -354,18 +366,18 @@ export default {
|
|||
},
|
||||
tempRecipe: {},
|
||||
tags: undefined,
|
||||
modalOpen: false,
|
||||
// newRecipeID: null,
|
||||
saving: false,
|
||||
modalOpen: 0,
|
||||
saving: 0,
|
||||
cacheImagePath: null,
|
||||
unSyncCombinations: [],
|
||||
difficultyLevels: ["Easy", "Moderate", "Challenging"],
|
||||
appbar: null,
|
||||
snackbar: null,
|
||||
scrollPos: 1,
|
||||
countdown: 5,
|
||||
snackMsg: null,
|
||||
showUndo: false,
|
||||
undo: false,
|
||||
showUndo: 0,
|
||||
undo: 0,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -376,37 +388,42 @@ export default {
|
|||
"recipes",
|
||||
"cuisines",
|
||||
"categories",
|
||||
"currentComponent",
|
||||
"selectedCuisine",
|
||||
"selectedCategory",
|
||||
"selectedTag",
|
||||
"appTheme",
|
||||
"selCuisine",
|
||||
"selCategory",
|
||||
"selTag",
|
||||
"theme",
|
||||
"RTL",
|
||||
]),
|
||||
screenWidth() {
|
||||
return Screen.mainScreen.widthDIPs;
|
||||
},
|
||||
hasChanges() {
|
||||
return JSON.stringify(this.recipe) !== JSON.stringify(this.tempRecipe);
|
||||
return JSON.stringify(this.recipe) != JSON.stringify(this.tempRecipe);
|
||||
},
|
||||
hasBackStack() {
|
||||
return Frame.topmost().backStack.length;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions([
|
||||
"setComponent",
|
||||
"addRecipeAction",
|
||||
"addListItemAction",
|
||||
"unSyncCombinationsAction",
|
||||
]),
|
||||
onPageLoad({ object }) {
|
||||
pgLoad({ object }) {
|
||||
object.bindingContext = new Observable();
|
||||
this.hijackBackEvent();
|
||||
},
|
||||
onPageUnload() {
|
||||
this.releaseBackEvent();
|
||||
},
|
||||
onAppBarLoad({ object }) {
|
||||
this.appbar = object;
|
||||
abLoad(args) {
|
||||
this.appbar = args.object;
|
||||
},
|
||||
onScroll(args) {
|
||||
sbLoad({ object }) {
|
||||
this.snackbar = object;
|
||||
},
|
||||
svLoad(args) {
|
||||
let scrollUp;
|
||||
let y = args.scrollY;
|
||||
if (y) {
|
||||
|
@ -416,14 +433,14 @@ export default {
|
|||
if (!scrollUp && ab == 0) {
|
||||
this.appbar.animate({
|
||||
translate: { x: 0, y: 64 },
|
||||
duration: 250,
|
||||
duration: 200,
|
||||
curve: CoreTypes.AnimationCurve.ease,
|
||||
});
|
||||
} else if (scrollUp && ab == 64) {
|
||||
Utils.ad.dismissSoftInput();
|
||||
this.appbar.animate({
|
||||
translate: { x: 0, y: 0 },
|
||||
duration: 250,
|
||||
duration: 200,
|
||||
curve: CoreTypes.AnimationCurve.ease,
|
||||
});
|
||||
}
|
||||
|
@ -432,16 +449,16 @@ export default {
|
|||
|
||||
// PHOTO HANDLERS
|
||||
imageHandler() {
|
||||
this.clearEmptyFields(true);
|
||||
this.clearEmptyFields(1);
|
||||
if (this.recipe.image) {
|
||||
this.modalOpen = true;
|
||||
this.modalOpen = 1;
|
||||
this.$showModal(Action, {
|
||||
props: {
|
||||
title: "recPic",
|
||||
list: ["aap", "rp"],
|
||||
},
|
||||
}).then((action) => {
|
||||
this.modalOpen = false;
|
||||
this.modalOpen = 0;
|
||||
switch (action) {
|
||||
case "aap":
|
||||
this.imagePicker();
|
||||
|
@ -454,12 +471,12 @@ export default {
|
|||
} else this.imagePicker();
|
||||
},
|
||||
imagePicker() {
|
||||
let aT = this.appTheme;
|
||||
let aT = this.theme;
|
||||
utils.getRecipePhoto().then((uri) => {
|
||||
if (uri != null) {
|
||||
this.cacheImagePath = path.join(
|
||||
knownFolders.temp().path,
|
||||
`${this.getRandomID()}.jpg`
|
||||
`${utils.getRandomID(0)}.jpg`
|
||||
);
|
||||
utils.copyPhotoToCache(uri, this.cacheImagePath).then((imgPath) => {
|
||||
if (imgPath) {
|
||||
|
@ -495,15 +512,27 @@ export default {
|
|||
}
|
||||
});
|
||||
},
|
||||
createDupImage() {
|
||||
if (this.recipe.image) {
|
||||
let cachePath = path.join(
|
||||
knownFolders.temp().path,
|
||||
`${utils.getRandomID(0)}.jpg`
|
||||
);
|
||||
utils.copyPhotoToCache(this.recipe.image, cachePath).then((imgPath) => {
|
||||
if (imgPath) this.recipe.image = imgPath;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// DATA LIST
|
||||
showCuisine(focus) {
|
||||
this.modalOpen = true;
|
||||
this.modalOpen = 1;
|
||||
this.$showModal(Action, {
|
||||
props: {
|
||||
title: "cui",
|
||||
list: this.cuisines,
|
||||
action: "aNBtn",
|
||||
selected: this.recipe.cuisine,
|
||||
},
|
||||
}).then((action) => {
|
||||
if (action == "aNBtn") {
|
||||
|
@ -513,21 +542,21 @@ export default {
|
|||
action: "aBtn",
|
||||
},
|
||||
}).then((item) => {
|
||||
this.modalOpen = false;
|
||||
this.modalOpen = 0;
|
||||
if (item.length) {
|
||||
this.recipe.cuisine = item;
|
||||
this.addListItemAction({
|
||||
item,
|
||||
listName: "cuisines",
|
||||
});
|
||||
if (focus) this.autoFocusField("category", false);
|
||||
if (focus) this.autoFocusField("category", 0);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.modalOpen = false;
|
||||
this.modalOpen = 0;
|
||||
if (action) {
|
||||
this.recipe.cuisine = action;
|
||||
if (focus) this.autoFocusField("category", false);
|
||||
if (focus) this.autoFocusField("category", 0);
|
||||
} else
|
||||
this.cuisines.includes(this.recipe.cuisine)
|
||||
? mull
|
||||
|
@ -536,12 +565,13 @@ export default {
|
|||
});
|
||||
},
|
||||
showCategories(focus) {
|
||||
this.modalOpen = true;
|
||||
this.modalOpen = 1;
|
||||
this.$showModal(Action, {
|
||||
props: {
|
||||
title: "cat",
|
||||
list: this.categories,
|
||||
action: "aNBtn",
|
||||
selected: this.recipe.category,
|
||||
},
|
||||
}).then((action) => {
|
||||
if (action == "aNBtn") {
|
||||
|
@ -551,21 +581,21 @@ export default {
|
|||
action: "aBtn",
|
||||
},
|
||||
}).then((item) => {
|
||||
this.modalOpen = false;
|
||||
this.modalOpen = 0;
|
||||
if (item.length) {
|
||||
this.recipe.category = item;
|
||||
this.addListItemAction({
|
||||
item,
|
||||
listName: "categories",
|
||||
});
|
||||
if (focus) this.autoFocusField("tags", true);
|
||||
if (focus) this.autoFocusField("tags", 1);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.modalOpen = false;
|
||||
this.modalOpen = 0;
|
||||
if (action) {
|
||||
this.recipe.category = action;
|
||||
if (focus) this.autoFocusField("tags", true);
|
||||
if (focus) this.autoFocusField("tags", 1);
|
||||
} else
|
||||
this.categories.includes(this.recipe.category)
|
||||
? mull
|
||||
|
@ -574,12 +604,13 @@ export default {
|
|||
});
|
||||
},
|
||||
showYieldUnits(focus) {
|
||||
this.modalOpen = true;
|
||||
this.modalOpen = 1;
|
||||
this.$showModal(Action, {
|
||||
props: {
|
||||
title: "yieldU",
|
||||
list: this.yieldUnits,
|
||||
action: "aNBtn",
|
||||
selected: this.recipe.yieldUnit,
|
||||
},
|
||||
}).then((action) => {
|
||||
if (action == "aNBtn") {
|
||||
|
@ -589,21 +620,21 @@ export default {
|
|||
action: "aBtn",
|
||||
},
|
||||
}).then((item) => {
|
||||
this.modalOpen = false;
|
||||
this.modalOpen = 0;
|
||||
if (item.length) {
|
||||
this.recipe.yieldUnit = item;
|
||||
this.addListItemAction({
|
||||
item,
|
||||
listName: "yieldUnits",
|
||||
});
|
||||
if (focus) this.autoFocusField("difficultyLevel", false);
|
||||
if (focus) this.autoFocusField("difficultyLevel", 0);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.modalOpen = false;
|
||||
this.modalOpen = 0;
|
||||
if (action) {
|
||||
this.recipe.yieldUnit = action;
|
||||
if (focus) this.autoFocusField("difficultyLevel", false);
|
||||
if (focus) this.autoFocusField("difficultyLevel", 0);
|
||||
} else
|
||||
this.yieldUnits.includes(this.recipe.yieldUnit)
|
||||
? mull
|
||||
|
@ -612,14 +643,15 @@ export default {
|
|||
});
|
||||
},
|
||||
showDifficultyLevel(focus) {
|
||||
this.modalOpen = true;
|
||||
this.modalOpen = 1;
|
||||
this.$showModal(Action, {
|
||||
props: {
|
||||
title: "Difficulty level",
|
||||
list: this.difficultyLevels,
|
||||
selected: this.recipe.difficulty,
|
||||
},
|
||||
}).then((action) => {
|
||||
this.modalOpen = false;
|
||||
this.modalOpen = 0;
|
||||
if (action) {
|
||||
this.recipe.difficulty = action;
|
||||
if (focus) this.addIngredient();
|
||||
|
@ -630,12 +662,13 @@ export default {
|
|||
});
|
||||
},
|
||||
showUnits(e, focus, index) {
|
||||
this.modalOpen = true;
|
||||
this.modalOpen = 1;
|
||||
this.$showModal(Action, {
|
||||
props: {
|
||||
title: "Unit",
|
||||
list: this.units,
|
||||
action: "aNBtn",
|
||||
selected: this.recipe.ingredients[index].unit,
|
||||
},
|
||||
}).then((action) => {
|
||||
if (action == "aNBtn") {
|
||||
|
@ -645,7 +678,7 @@ export default {
|
|||
action: "aBtn",
|
||||
},
|
||||
}).then((item) => {
|
||||
this.modalOpen = false;
|
||||
this.modalOpen = 0;
|
||||
if (item.length) {
|
||||
this.recipe.ingredients[index].unit = item;
|
||||
this.addListItemAction({
|
||||
|
@ -657,7 +690,7 @@ export default {
|
|||
}
|
||||
});
|
||||
} else {
|
||||
this.modalOpen = false;
|
||||
this.modalOpen = 0;
|
||||
if (action) {
|
||||
this.recipe.ingredients[index].unit = action;
|
||||
if (focus && this.recipe.ingredients.length - 1 === index)
|
||||
|
@ -668,7 +701,7 @@ export default {
|
|||
},
|
||||
showCombinations() {
|
||||
Utils.ad.dismissSoftInput();
|
||||
this.modalOpen = true;
|
||||
this.modalOpen = 1;
|
||||
let existingCombinations = [...this.recipe.combinations, this.recipe.id];
|
||||
let filteredRecipes = this.recipes.filter(
|
||||
(e) => !existingCombinations.includes(e.id)
|
||||
|
@ -679,7 +712,7 @@ export default {
|
|||
recipes: filteredRecipes,
|
||||
},
|
||||
}).then((res) => {
|
||||
this.modalOpen = false;
|
||||
this.modalOpen = 0;
|
||||
if (res) this.recipe.combinations.push(res);
|
||||
});
|
||||
},
|
||||
|
@ -697,7 +730,7 @@ export default {
|
|||
});
|
||||
},
|
||||
removeIngredient(index) {
|
||||
this.modalOpen = true;
|
||||
this.modalOpen = 1;
|
||||
if (this.recipe.ingredients[index].item.length) {
|
||||
let item = this.recipe.ingredients[index];
|
||||
this.recipe.ingredients.splice(index, 1);
|
||||
|
@ -707,7 +740,7 @@ export default {
|
|||
} else {
|
||||
this.recipe.ingredients.splice(index, 1);
|
||||
}
|
||||
setTimeout(() => (this.modalOpen = false), 200);
|
||||
setTimeout(() => (this.modalOpen = 0), 200);
|
||||
},
|
||||
addInstruction() {
|
||||
this.recipe.instructions.push("");
|
||||
|
@ -759,17 +792,17 @@ export default {
|
|||
clearEmpty("notes");
|
||||
},
|
||||
saveOperation() {
|
||||
this.saving = this.modalOpen = true;
|
||||
this.saving = this.modalOpen = 1;
|
||||
this.clearEmptyFields();
|
||||
this.recipe.lastModified = new Date().getTime();
|
||||
ApplicationSettings.setString("previousCuisine", this.recipe.cuisine);
|
||||
ApplicationSettings.setString("previousCategory", this.recipe.category);
|
||||
ApplicationSettings.setString("previousYieldUnit", this.recipe.yieldUnit);
|
||||
setString("previousCuisine", this.recipe.cuisine);
|
||||
setString("previousCategory", this.recipe.category);
|
||||
setString("previousYieldUnit", this.recipe.yieldUnit);
|
||||
if (this.cacheImagePath) {
|
||||
let recipeImage = path.join(
|
||||
knownFolders.documents().getFolder("EnRecipes").getFolder("Images")
|
||||
.path,
|
||||
`${this.getRandomID()}.jpg`
|
||||
`${utils.getRandomID(0)}.jpg`
|
||||
);
|
||||
let binarySource = File.fromPath(this.cacheImagePath).readSync();
|
||||
File.fromPath(recipeImage).writeSync(binarySource);
|
||||
|
@ -794,57 +827,49 @@ export default {
|
|||
},
|
||||
saveRecipe() {
|
||||
this.addRecipeAction(this.recipe);
|
||||
setTimeout(() => (this.saving = false), 100);
|
||||
this.$navigateBack();
|
||||
this.saving = 0;
|
||||
this.dupRecipe
|
||||
? this.$navigateTo(EnRecipes, {
|
||||
clearHistory: true,
|
||||
animated: false,
|
||||
})
|
||||
: this.goBackAction(0);
|
||||
},
|
||||
|
||||
// UNDO OPERATION
|
||||
showUndoBar(message) {
|
||||
clearInterval(barTimer);
|
||||
return new Promise((resolve, reject) => {
|
||||
this.showUndo = true;
|
||||
this.appbar.translateY = 0;
|
||||
this.snackMsg = message;
|
||||
this.countdown = 5;
|
||||
let a = 5;
|
||||
clearTimeout(undoTimer);
|
||||
undoTimer = setInterval(() => {
|
||||
if (this.undo) {
|
||||
this.showUndo = this.undo = false;
|
||||
clearTimeout(undoTimer);
|
||||
resolve(true);
|
||||
}
|
||||
this.countdown = Math.round((a -= 0.1));
|
||||
if (this.countdown < 1) {
|
||||
this.showUndo = false;
|
||||
clearTimeout(undoTimer);
|
||||
reject(true);
|
||||
}
|
||||
}, 100);
|
||||
this.animateBar(this.appbar, 0).then(() => {
|
||||
this.showUndo = 1;
|
||||
this.snackMsg = message;
|
||||
this.countdown = 5;
|
||||
this.animateBar(this.snackbar, 1).then(() => {
|
||||
let a = 5;
|
||||
barTimer = setInterval(() => {
|
||||
if (this.undo) {
|
||||
this.hideBar();
|
||||
resolve(1);
|
||||
}
|
||||
this.countdown = Math.round((a -= 0.1));
|
||||
if (this.countdown < 1) {
|
||||
this.hideBar();
|
||||
reject(1);
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
hideUndoBar({ object }) {
|
||||
object
|
||||
.animate({
|
||||
opacity: 0,
|
||||
translate: { x: 0, y: 64 },
|
||||
duration: 250,
|
||||
curve: CoreTypes.AnimationCurve.ease,
|
||||
})
|
||||
.then(() => {
|
||||
this.showUndo = false;
|
||||
this.appbar.translateY = 64;
|
||||
this.appbar.animate({
|
||||
translate: { x: 0, y: 0 },
|
||||
duration: 250,
|
||||
curve: CoreTypes.AnimationCurve.ease,
|
||||
});
|
||||
object.opacity = 1;
|
||||
object.translateY = 0;
|
||||
clearTimeout(undoTimer);
|
||||
});
|
||||
hideBar() {
|
||||
clearInterval(barTimer);
|
||||
this.animateBar(this.snackbar, 0).then(() => {
|
||||
this.showUndo = this.undo = 0;
|
||||
this.animateBar(this.appbar, 1);
|
||||
});
|
||||
},
|
||||
undoDel() {
|
||||
this.undo = true;
|
||||
this.undo = 1;
|
||||
},
|
||||
|
||||
// HELPERS
|
||||
|
@ -891,29 +916,30 @@ export default {
|
|||
},
|
||||
focusField(args, type) {
|
||||
if (type) this.setInputTypeText(args, type);
|
||||
else this.setGravity(args);
|
||||
if (!args.object.text) {
|
||||
args.object.focus();
|
||||
setTimeout(() => Utils.ad.showSoftInput(args.object.android), 100);
|
||||
}
|
||||
},
|
||||
setInputTypeText(args, type) {
|
||||
let field = args.object;
|
||||
setInputTypeText({ object }, type) {
|
||||
this.setGravity(object);
|
||||
let common =
|
||||
android.text.InputType.TYPE_CLASS_TEXT |
|
||||
android.text.InputType.TYPE_TEXT_FLAG_AUTO_CORRECT;
|
||||
switch (type) {
|
||||
case "words":
|
||||
field.android.setInputType(
|
||||
object.android.setInputType(
|
||||
android.text.InputType.TYPE_TEXT_FLAG_CAP_WORDS | common
|
||||
);
|
||||
break;
|
||||
case "sentence":
|
||||
field.android.setInputType(
|
||||
object.android.setInputType(
|
||||
android.text.InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | common
|
||||
);
|
||||
break;
|
||||
case "multiLine":
|
||||
field.android.setInputType(
|
||||
object.android.setInputType(
|
||||
android.text.InputType.TYPE_TEXT_FLAG_MULTI_LINE |
|
||||
android.text.InputType.TYPE_TEXT_FLAG_CAP_SENTENCES |
|
||||
common
|
||||
|
@ -921,37 +947,28 @@ export default {
|
|||
break;
|
||||
}
|
||||
},
|
||||
getRandomID() {
|
||||
let res = "";
|
||||
let chars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||
for (let i = 0; i < 16; i++) {
|
||||
res += chars.charAt(Math.floor(Math.random() * chars.length));
|
||||
}
|
||||
return res;
|
||||
},
|
||||
setTimeRequired(focus, time) {
|
||||
this.modalOpen = true;
|
||||
this.modalOpen = 1;
|
||||
let t = this.recipe[time].split(":");
|
||||
let hr = t[0];
|
||||
let min = t[1];
|
||||
this.$showModal(TimePickerHM, {
|
||||
props: {
|
||||
title: `${time == "prepTime" ? "prepT" : "cookT"}`,
|
||||
action: "SET",
|
||||
selectedHr: hr,
|
||||
selectedMin: min,
|
||||
},
|
||||
}).then((result) => {
|
||||
this.modalOpen = false;
|
||||
this.modalOpen = 0;
|
||||
if (result) {
|
||||
this.recipe[time] = result;
|
||||
if (focus) {
|
||||
switch (time) {
|
||||
case "prepTime":
|
||||
this.autoFocusField("cookTime", false);
|
||||
this.autoFocusField("cookTime", 0);
|
||||
break;
|
||||
case "cookTime":
|
||||
this.autoFocusField("yieldQuantity", true);
|
||||
this.autoFocusField("yieldQuantity", 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -980,12 +997,22 @@ export default {
|
|||
backEvent(args) {
|
||||
if (!this.modalOpen) {
|
||||
args.cancel = true;
|
||||
this.navigateBack();
|
||||
this.navigateBack(1);
|
||||
}
|
||||
},
|
||||
navigateBack() {
|
||||
goBackAction(exit) {
|
||||
this.hasBackStack || this.recipeID
|
||||
? this.$navigateBack()
|
||||
: exit
|
||||
? Application.android.foregroundActivity.finish()
|
||||
: this.$navigateTo(EnRecipes, {
|
||||
clearHistory: true,
|
||||
animated: false,
|
||||
});
|
||||
},
|
||||
navigateBack(hwb) {
|
||||
if (this.hasChanges) {
|
||||
this.modalOpen = true;
|
||||
this.modalOpen = 1;
|
||||
this.$showModal(Confirm, {
|
||||
props: {
|
||||
title: "unsaved",
|
||||
|
@ -994,46 +1021,47 @@ export default {
|
|||
okButtonText: "kEdit",
|
||||
},
|
||||
}).then((action) => {
|
||||
this.modalOpen = false;
|
||||
if (action != null && !action) this.$navigateBack();
|
||||
this.modalOpen = 0;
|
||||
if (action != null && !action) {
|
||||
this.goBackAction(1);
|
||||
knownFolders.temp().clear();
|
||||
}
|
||||
});
|
||||
} else this.$navigateBack();
|
||||
} else this.goBackAction(hwb);
|
||||
},
|
||||
},
|
||||
created() {
|
||||
setTimeout(() => {
|
||||
this.setComponent("EditRecipe");
|
||||
}, 500);
|
||||
this.title = this.recipeID ? "editRec" : "newRec";
|
||||
this.title = this.recipeID || this.dupRecipe ? "editRec" : "newRec";
|
||||
if (this.recipeID) {
|
||||
let recipe = this.recipes.filter((e) => e.id === this.recipeID)[0];
|
||||
Object.assign(this.recipe, JSON.parse(JSON.stringify(recipe)));
|
||||
Object.assign(this.tempRecipe, JSON.parse(JSON.stringify(this.recipe)));
|
||||
if (this.recipe.tags.length) this.joinTags();
|
||||
} else if (this.dupRecipe) {
|
||||
this.recipe = Object.assign({}, this.dupRecipe);
|
||||
this.recipe.tried = 1;
|
||||
this.recipe.lastTried = 0;
|
||||
this.createDupImage();
|
||||
} else {
|
||||
this.recipe.cuisine = this.selectedCuisine
|
||||
? /all/.test(this.selectedCuisine)
|
||||
this.recipe.cuisine = this.selCuisine
|
||||
? /all/.test(this.selCuisine)
|
||||
? "Undefined"
|
||||
: this.selectedCuisine
|
||||
: ApplicationSettings.getString("previousCuisine", "Undefined");
|
||||
this.recipe.category = this.selectedCategory
|
||||
? /all/.test(this.selectedCategory)
|
||||
: this.selCuisine
|
||||
: getString("previousCuisine", "Undefined");
|
||||
this.recipe.category = this.selCategory
|
||||
? /all/.test(this.selCategory)
|
||||
? "Undefined"
|
||||
: this.selectedCategory
|
||||
: ApplicationSettings.getString("previousCategory", "Undefined");
|
||||
if (this.selectedTag && !/all/.test(this.selectedTag)) {
|
||||
this.tags = this.selectedTag;
|
||||
: this.selCategory
|
||||
: getString("previousCategory", "Undefined");
|
||||
if (this.selTag && !/all/.test(this.selTag)) {
|
||||
this.tags = this.selTag;
|
||||
this.splitTags();
|
||||
}
|
||||
this.recipe.yieldUnit = ApplicationSettings.getString(
|
||||
"previousYieldUnit",
|
||||
"Serving"
|
||||
);
|
||||
if (this.filterFavourites) this.recipe.favorite = true;
|
||||
if (this.filterTrylater) this.recipe.tried = false;
|
||||
this.recipe.yieldUnit = getString("previousYieldUnit", "Serving");
|
||||
if (this.filterFavourites) this.recipe.favorite = 1;
|
||||
if (this.filterTrylater) this.recipe.tried = 0;
|
||||
this.recipe.created = new Date().getTime();
|
||||
Object.assign(this.tempRecipe, JSON.parse(JSON.stringify(this.recipe)));
|
||||
// this.newRecipeID = this.getRandomID();
|
||||
this.tempRecipe = Object.assign({}, this.recipe);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
<template>
|
||||
<Page @loaded="onPageLoad">
|
||||
<ActionBar flat="true">
|
||||
<GridLayout rows="*" columns="auto, *, auto">
|
||||
<Button class="ico left" :text="icon.back" @tap="$navigateBack()" />
|
||||
<Label class="title tb" :text="'grocery' | L" col="1" />
|
||||
<Button class="ico left" :text="icon.today" col="2" />
|
||||
</GridLayout>
|
||||
</ActionBar>
|
||||
<GridLayout columns="" rows=""> </GridLayout>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ApplicationSettings, Observable } from "@nativescript/core";
|
||||
import { mapState, mapActions } from "vuex";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
appTheme: "Light",
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(["icon", "recipes", "mealPlans"]),
|
||||
isLightMode() {
|
||||
return this.appTheme === "Light";
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions(["setComponent"]),
|
||||
onPageLoad({ object }) {
|
||||
object.bindingContext = new Observable();
|
||||
this.setComponent("GroceryList");
|
||||
},
|
||||
// HELPERS
|
||||
|
||||
// NAVIGATION HANDLERS
|
||||
viewRecipe(recipeID) {
|
||||
let recipe = this.recipes.filter((e) => e.id === recipeID)[0];
|
||||
if (recipe) {
|
||||
this.$navigateTo(ViewRecipe, {
|
||||
props: {
|
||||
filterTrylater: true,
|
||||
recipeID,
|
||||
},
|
||||
backstackVisible: false,
|
||||
});
|
||||
}
|
||||
},
|
||||
// DATA HANDLERS
|
||||
},
|
||||
created() {
|
||||
this.appTheme = ApplicationSettings.getString("appTheme", "Light");
|
||||
},
|
||||
};
|
||||
</script>
|
|
@ -1,112 +1,146 @@
|
|||
<template>
|
||||
<Page @loaded="pgLoad" actionBarHidden="true">
|
||||
<GridLayout rows="*, auto" columns="*">
|
||||
<GridLayout rows="*, auto, 72" columns="*">
|
||||
<ScrollView
|
||||
@scroll="!edit && svLoad($event)"
|
||||
rowSpan="2"
|
||||
@scroll="!edit && svScroll($event)"
|
||||
rowSpan="3"
|
||||
scrollBarIndicatorVisible="false"
|
||||
>
|
||||
<StackLayout>
|
||||
<GridLayout rows="auto" columns="*, auto, 8">
|
||||
<Label class="pageTitle" :text="'planner' | L" />
|
||||
<Button
|
||||
<RGridLayout :rtl="RTL" columns="*, auto, 12">
|
||||
<Label class="pageTitle a" :text="'planner' | L" />
|
||||
<Button col="1" class="ico" :text="icon.cog" @tap="navigateTo" />
|
||||
</RGridLayout>
|
||||
<GridLayout class="monthSwitcher" columns="auto, *, auto">
|
||||
<Button class="ico min" :text="icon.left" @tap="navigate(0)" />
|
||||
<Label
|
||||
class="month"
|
||||
@touch="mYPicker"
|
||||
col="1"
|
||||
class="ico"
|
||||
:text="icon.cog"
|
||||
@tap="$navigateTo(MPSettings)"
|
||||
:text="formattedDate(0)"
|
||||
/>
|
||||
<Button
|
||||
class="ico min"
|
||||
col="2"
|
||||
:text="icon.right"
|
||||
@tap="navigate(1)"
|
||||
/>
|
||||
</GridLayout>
|
||||
<GridLayout
|
||||
<RGridLayout
|
||||
:rtl="RTL"
|
||||
class="calendar"
|
||||
columns="*, *, *, *, *, *, *"
|
||||
rows="auto, auto, auto, auto, auto, auto, auto, auto"
|
||||
:rows="calRows"
|
||||
>
|
||||
<Button class="ico navBtn" :text="icon.left" @tap="prevMonth" />
|
||||
<Label
|
||||
class="monthName"
|
||||
@touch="touchMonthYearPicker"
|
||||
col="1"
|
||||
colSpan="5"
|
||||
:text="$options.filters.L(mNames[month]) + ' ' + year"
|
||||
/>
|
||||
<Button
|
||||
class="ico navBtn"
|
||||
col="6"
|
||||
:text="icon.right"
|
||||
@tap="nextMonth"
|
||||
/>
|
||||
<Label
|
||||
class="dayName"
|
||||
row="1"
|
||||
class="dayName sub rtl"
|
||||
:class="{ f: RTL }"
|
||||
:col="i"
|
||||
v-for="(d, i) in getDayNames"
|
||||
:key="d"
|
||||
:key="d + i"
|
||||
:text="d | L"
|
||||
/>
|
||||
<Button
|
||||
class="min day"
|
||||
:class="{
|
||||
tb: isToday(d),
|
||||
activeDay: isActive(d),
|
||||
hasPlans: hasPlans(d),
|
||||
}"
|
||||
v-for="(cal, i) in getCal"
|
||||
:key="i"
|
||||
:row="getrow(i)"
|
||||
:col="i % 7"
|
||||
v-for="(d, i) in getCal"
|
||||
:key="i"
|
||||
:text="d ? d : null"
|
||||
@tap="setToday(d)"
|
||||
:class="dayClasses(cal)"
|
||||
:text="cal.ld"
|
||||
@tap="setDate(cal)"
|
||||
/>
|
||||
</GridLayout>
|
||||
<StackLayout class="dayPlan">
|
||||
<StackLayout
|
||||
v-for="(mealType, index) in mealTimesWithRecipes"
|
||||
:key="'mealType' + index"
|
||||
>
|
||||
<GridLayout columns="auto, auto">
|
||||
<Label
|
||||
class="periodLabel tb"
|
||||
:class="mealType"
|
||||
:text="mealType | L"
|
||||
/>
|
||||
<Button
|
||||
:visibility="edit ? 'visible' : 'hidden'"
|
||||
col="1"
|
||||
class="ico"
|
||||
:text="icon.plus"
|
||||
@tap="addRecipe(mealType)"
|
||||
/>
|
||||
</GridLayout>
|
||||
<GridLayout
|
||||
:columns="`*, ${edit ? 'auto' : 0}`"
|
||||
v-for="(recipeID, index) in getRecipes[mealType]"
|
||||
:key="mealType + index"
|
||||
</RGridLayout>
|
||||
<StackLayout class="plans">
|
||||
<RLabel
|
||||
v-if="plannerView != 'd' && mealPlans.length"
|
||||
class="date tb"
|
||||
:text="formattedDate(1)"
|
||||
textWrap="true"
|
||||
/>
|
||||
<StackLayout v-for="(meal, i) in mealTypes" :key="'meal' + i">
|
||||
<Label
|
||||
:hidden="!getRecipes[meal]"
|
||||
class="meal tb"
|
||||
:class="[meal]"
|
||||
:text="meal | L"
|
||||
/>
|
||||
<RGridLayout
|
||||
:rtl="RTL"
|
||||
v-for="(plan, i) in getRecipes[meal]"
|
||||
:key="meal + i"
|
||||
class="plan"
|
||||
columns="*, auto"
|
||||
>
|
||||
<Button
|
||||
class="recipeTitle"
|
||||
:text="getRecipeTitle(recipeID)"
|
||||
@tap="viewRecipe(recipeID)"
|
||||
<RGridLayout
|
||||
:rtl="RTL"
|
||||
class="rtl"
|
||||
:hidden="!plan.recipeID"
|
||||
:columns="noImg ? '*' : '48, *'"
|
||||
@touch="touchRecipe"
|
||||
@tap="viewRecipe(plan.id)"
|
||||
>
|
||||
<Image
|
||||
class="imgHolder"
|
||||
verticalAlignment="middle"
|
||||
v-if="!noImg && getRecipeImage(plan.recipeID)"
|
||||
:src="getRecipeImage(plan.recipeID)"
|
||||
stretch="none"
|
||||
decodeWidth="48"
|
||||
decodeHeight="48"
|
||||
loadMode="async"
|
||||
/>
|
||||
<Label
|
||||
v-else-if="!noImg && !getRecipeImage(plan.recipeID)"
|
||||
verticalAlignment="middle"
|
||||
class="ico imgHolder"
|
||||
@loaded="centerLabel($event, 17)"
|
||||
width="48"
|
||||
height="48"
|
||||
fontSize="24"
|
||||
:text="icon.img"
|
||||
/>
|
||||
<StackLayout class="planContent" col="1">
|
||||
<RLabel
|
||||
class="title"
|
||||
:text="getRecipeTitle(plan.recipeID)"
|
||||
/>
|
||||
<RLabel class="attr" :text="getYield(plan.id)" />
|
||||
</StackLayout>
|
||||
</RGridLayout>
|
||||
<Label
|
||||
class="planContent tw"
|
||||
@loaded="centerLabel($event, 16)"
|
||||
:hidden="!plan.note"
|
||||
:text="plan.note"
|
||||
/>
|
||||
<Button
|
||||
:visibility="edit ? 'visible' : 'hidden'"
|
||||
:hidden="!edit"
|
||||
col="1"
|
||||
class="ico x"
|
||||
class="ico min"
|
||||
:text="icon.x"
|
||||
@tap="removeRecipe(mealType, recipeID)"
|
||||
@tap="removeRecipe(plan.id)"
|
||||
/>
|
||||
</GridLayout>
|
||||
</RGridLayout>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</ScrollView>
|
||||
<GridLayout
|
||||
row="1"
|
||||
<GridLayout rowSpan="2" rows="*, auto" v-if="!mealPlans.length">
|
||||
<StackLayout row="1" class="emptyState">
|
||||
<RLabel class="title" :text="'ehwmp' | L" />
|
||||
<RLabel :text="'plsCrt' | L" />
|
||||
</StackLayout>
|
||||
</GridLayout>
|
||||
<RGridLayout
|
||||
:rtl="RTL"
|
||||
row="2"
|
||||
@loaded="abLoad"
|
||||
class="appbar"
|
||||
:hidden="showUndo"
|
||||
columns="auto, *, auto, auto"
|
||||
columns="auto, *, auto, auto, auto"
|
||||
@swipe="stSwipe"
|
||||
>
|
||||
<Button class="ico" :text="icon.back" @tap="$navigateBack()" />
|
||||
<Button class="ico rtl" :text="icon.back" @tap="navigateBack" />
|
||||
<Button
|
||||
class="ico"
|
||||
:text="icon.tod"
|
||||
|
@ -115,13 +149,22 @@
|
|||
col="2"
|
||||
/>
|
||||
<Button
|
||||
class="ico fab"
|
||||
:hidden="!hasRecipes"
|
||||
class="ico"
|
||||
:text="edit ? icon.done : icon.edit"
|
||||
@tap="toggleEditMode"
|
||||
col="3"
|
||||
/>
|
||||
</GridLayout>
|
||||
<!-- <Button
|
||||
class="ico"
|
||||
:text="hasRecipes ? (edit ? icon.done : icon.edit) : icon.madd"
|
||||
@tap="hasRecipes ? toggleEditMode() : randomMealPlan()"
|
||||
col="3"
|
||||
/> -->
|
||||
<Button class="ico fab" :text="icon.plus" @tap="addMealPlan" col="4" />
|
||||
</RGridLayout>
|
||||
<SnackBar
|
||||
row="2"
|
||||
:hidden="!showUndo"
|
||||
:count="countdown"
|
||||
:msg="snackMsg"
|
||||
|
@ -133,14 +176,21 @@
|
|||
</Page>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Observable, CoreTypes } from "@nativescript/core";
|
||||
<script lang="ts">
|
||||
import { Frame, Observable, CoreTypes, Screen } from "@nativescript/core";
|
||||
import { mapState, mapActions } from "vuex";
|
||||
import ViewRecipe from "./ViewRecipe";
|
||||
import MPSettings from "./settings/MPSettings";
|
||||
import ActionWithSearch from "./modals/ActionWithSearch";
|
||||
import MonthYearPicker from "./modals/MonthYearPicker";
|
||||
import SnackBar from "./sub/SnackBar";
|
||||
import ViewRecipe from "./ViewRecipe.vue";
|
||||
import EditRecipe from "./EditRecipe.vue";
|
||||
import EnRecipes from "./EnRecipes.vue";
|
||||
import MPSettings from "./settings/MPSettings.vue";
|
||||
import Action from "./modals/Action.vue";
|
||||
import ActionWithSearch from "./modals/ActionWithSearch.vue";
|
||||
import Prompt from "./modals/Prompt.vue";
|
||||
import DMYPicker from "./modals/DMYPicker.vue";
|
||||
import SnackBar from "./sub/SnackBar.vue";
|
||||
import * as utils from "~/shared/utils";
|
||||
const Intl = require("nativescript-intl");
|
||||
import { localize } from "@nativescript/localize";
|
||||
let barTimer;
|
||||
|
||||
export default {
|
||||
|
@ -149,10 +199,9 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
mealTimes: ["breakfast", "lunch", "dinner", "snacks"],
|
||||
dNames: ["MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"],
|
||||
mealTypes: ["breakfast", "lunch", "dinner", "snacks"],
|
||||
year: 2021,
|
||||
mNames: [
|
||||
monthNames: [
|
||||
"January",
|
||||
"February",
|
||||
"March",
|
||||
|
@ -168,20 +217,27 @@ export default {
|
|||
],
|
||||
month: 0,
|
||||
date: null,
|
||||
edit: false,
|
||||
edit: 0,
|
||||
scrollPos: 1,
|
||||
appbar: null,
|
||||
snackbar: null,
|
||||
countdown: 5,
|
||||
snackMsg: null,
|
||||
showUndo: false,
|
||||
undo: false,
|
||||
MPSettings: MPSettings,
|
||||
showUndo: 0,
|
||||
undo: 0,
|
||||
temp: 0,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(["icon", "recipes", "mealPlans", "mondayFirst"]),
|
||||
...mapState([
|
||||
"icon",
|
||||
"recipes",
|
||||
"layout",
|
||||
"mealPlans",
|
||||
"mondayFirst",
|
||||
"RTL",
|
||||
"plannerView",
|
||||
]),
|
||||
todaysTime() {
|
||||
return new Date(this.year, this.month, this.date, 0).getTime();
|
||||
},
|
||||
|
@ -189,33 +245,58 @@ export default {
|
|||
if (this.mealPlans.length) {
|
||||
return this.mealPlans.reduce((acc, e) => {
|
||||
if (e.date == this.todaysTime) {
|
||||
acc[e.type] = [...(acc[e.type] || []), e.title];
|
||||
acc[e.mealType] = [...(acc[e.mealType] || []), e];
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
} else return 0;
|
||||
} else return {};
|
||||
},
|
||||
calRows() {
|
||||
let h = (Screen.mainScreen.widthDIPs - 32) / 8;
|
||||
let pv = this.plannerView;
|
||||
return pv != "d" ? `${h}, `.repeat(pv == "wk" ? 1 : 6) + h : 0;
|
||||
},
|
||||
getDayNames() {
|
||||
let dNames = [...this.dNames];
|
||||
if (!this.mondayFirst) dNames.unshift(dNames.pop());
|
||||
let dNames =
|
||||
this.plannerView != "d" &&
|
||||
this.getCal.slice(0, 7).map((d) => {
|
||||
let date = new Date(d.y, d.m, d.d);
|
||||
return new Intl.DateTimeFormat(null, {
|
||||
weekday: "short",
|
||||
}).format(date);
|
||||
});
|
||||
return dNames;
|
||||
},
|
||||
getCal() {
|
||||
let y = this.year;
|
||||
let m = this.month;
|
||||
let ds = new Date(y, m + 1, 0).getDate();
|
||||
let fd = new Date(y, m, 1).getDay();
|
||||
let ld = new Date(y, m, ds).getDay();
|
||||
if (this.mondayFirst) fd -= 1;
|
||||
let days = new Array(fd).fill(0);
|
||||
// let prevDays = Array.from(
|
||||
// { length: fd },
|
||||
// (e, k) => k + new Date(!m ? y - 1 : y, m, 0).getDate() - fd + 1
|
||||
// );
|
||||
// let days = prevDays;
|
||||
for (let i = 1; i <= ds; i++) days.push(i);
|
||||
// for (let i = 1; i <= 6 - ld; i++) days.push(i);
|
||||
return days;
|
||||
const getDays = (s, e) => {
|
||||
let a = [];
|
||||
for (
|
||||
let d = new Date(s);
|
||||
d <= new Date(e);
|
||||
d.setDate(d.getDate() + 1)
|
||||
) {
|
||||
a.push({
|
||||
d: d.getDate(),
|
||||
ld: this.getLocaleN(d.getDate()),
|
||||
m: d.getMonth(),
|
||||
y: d.getFullYear(),
|
||||
});
|
||||
}
|
||||
return a;
|
||||
};
|
||||
|
||||
let pv = this.plannerView;
|
||||
let date = new Date(
|
||||
this.year,
|
||||
this.month,
|
||||
pv == "mnth" ? 1 : this.date - this.mondayFirst
|
||||
);
|
||||
return pv != "d"
|
||||
? getDays(
|
||||
date.setDate(date.getDate() - date.getDay() + this.mondayFirst),
|
||||
date.setDate(date.getDate() + (pv == "mnth" ? 41 : 6))
|
||||
)
|
||||
: 0;
|
||||
},
|
||||
isExactlyToday() {
|
||||
let d = new Date();
|
||||
|
@ -225,22 +306,24 @@ export default {
|
|||
this.date == d.getDate()
|
||||
);
|
||||
},
|
||||
mealTimesWithRecipes() {
|
||||
return this.mealTimes.filter(
|
||||
(e) => (this.getRecipes[e] && this.getRecipes[e].length) || this.edit
|
||||
);
|
||||
hasRecipes() {
|
||||
return this.mealTypes.filter(
|
||||
(e) => this.getRecipes[e] && this.getRecipes[e].length
|
||||
).length;
|
||||
},
|
||||
noImg() {
|
||||
return /simple|minimal/.test(this.layout);
|
||||
},
|
||||
noAttr() {
|
||||
return /minimal/.test(this.layout);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions([
|
||||
"setComponent",
|
||||
"addMealPlanAction",
|
||||
"deleteMealPlanAction",
|
||||
]),
|
||||
...mapActions(["addMealPlanAction", "deleteMealPlanAction"]),
|
||||
pgLoad({ object }) {
|
||||
object.bindingContext = new Observable();
|
||||
this.setComponent("MealPlanner");
|
||||
if (!this.date || this.date === new Date().getDate()) this.goToToday();
|
||||
this.showBar();
|
||||
},
|
||||
abLoad({ object }) {
|
||||
this.appbar = object;
|
||||
|
@ -248,7 +331,7 @@ export default {
|
|||
sbLoad({ object }) {
|
||||
this.snackbar = object;
|
||||
},
|
||||
svLoad(args) {
|
||||
svScroll(args) {
|
||||
let scrollUp;
|
||||
let y = args.scrollY;
|
||||
if (y) {
|
||||
|
@ -258,96 +341,143 @@ export default {
|
|||
if (!scrollUp && ab == 0) {
|
||||
this.appbar.animate({
|
||||
translate: { x: 0, y: 64 },
|
||||
duration: 250,
|
||||
duration: 200,
|
||||
curve: CoreTypes.AnimationCurve.ease,
|
||||
});
|
||||
} else if (scrollUp && ab == 64) {
|
||||
this.appbar.animate({
|
||||
translate: { x: 0, y: 0 },
|
||||
duration: 250,
|
||||
duration: 200,
|
||||
curve: CoreTypes.AnimationCurve.ease,
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
// HELPERS
|
||||
showAppBar() {
|
||||
this.appbar.translateY = 0;
|
||||
|
||||
// Helpers
|
||||
centerLabel({ object }, n) {
|
||||
object.android.setGravity(n);
|
||||
},
|
||||
showBar() {
|
||||
// this.appbar.translateY = 0;
|
||||
this.appbar.animate({
|
||||
translate: { x: 0, y: 0 },
|
||||
duration: 200,
|
||||
curve: CoreTypes.AnimationCurve.ease,
|
||||
});
|
||||
},
|
||||
getrow(i) {
|
||||
return Math.floor(2 + i / 7);
|
||||
return Math.floor(1 + i / 7);
|
||||
},
|
||||
getDate(index) {
|
||||
let date = new Date();
|
||||
date.setDate(date.getDate() + index);
|
||||
return date.getTime();
|
||||
},
|
||||
getRecipeImage(id) {
|
||||
let r = this.recipes.filter((e) => e.id === id)[0];
|
||||
return r && r.image;
|
||||
},
|
||||
getRecipeTitle(id) {
|
||||
let recipe = this.recipes.filter((e) => e.id === id)[0];
|
||||
return recipe ? recipe.title : `[ ${this.$options.filters.L("resNF")} ]`;
|
||||
let r = this.recipes.filter((e) => e.id === id)[0];
|
||||
return r ? r.title : `[${this.$options.filters.L("resNF")}]`;
|
||||
},
|
||||
getRecipeTotalTime(id) {
|
||||
let r = this.recipes.filter((e) => e.id === id)[0];
|
||||
return r ? this.totalTime(r.prepTime, r.cookTime).time : "00:00";
|
||||
},
|
||||
getYield(id) {
|
||||
let mp = this.mealPlans.filter((e) => e.id == id)[0];
|
||||
let r = this.recipes.filter((e) => e.id === mp.recipeID)[0];
|
||||
return r ? `${this.getLocaleN(mp.quantity)} ${localize(r.yieldUnit)}` : 1;
|
||||
},
|
||||
|
||||
// NAVIGATION HANDLERS
|
||||
viewRecipe(recipeID) {
|
||||
let recipe = this.recipes.filter((e) => e.id === recipeID)[0];
|
||||
if (recipe) {
|
||||
// NavigationHandlers
|
||||
viewRecipe(id) {
|
||||
let mp = this.mealPlans.filter((e) => e.id == id)[0];
|
||||
let r = this.recipes.filter((e) => e.id === mp.recipeID)[0];
|
||||
if (r) {
|
||||
this.$navigateTo(ViewRecipe, {
|
||||
props: {
|
||||
filterTrylater: true,
|
||||
recipeID,
|
||||
filterTrylater: 1,
|
||||
recipeID: r.id,
|
||||
yieldQuantity: mp.quantity,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// CALENDAR
|
||||
prevMonth() {
|
||||
if (this.month == 0) {
|
||||
this.year--;
|
||||
this.month = 11;
|
||||
} else this.month--;
|
||||
this.showAppBar();
|
||||
navigateTo() {
|
||||
this.$navigateTo(MPSettings, {
|
||||
transition: {
|
||||
name: this.RTL ? "slideRight" : "slide",
|
||||
duration: 200,
|
||||
curve: "easeOut",
|
||||
},
|
||||
});
|
||||
},
|
||||
nextMonth() {
|
||||
if (this.month == 11) {
|
||||
this.year++;
|
||||
this.month = 0;
|
||||
} else this.month++;
|
||||
this.showAppBar();
|
||||
navigateBack() {
|
||||
Frame.topmost().backStack.length
|
||||
? this.$navigateBack()
|
||||
: this.$navigateTo(EnRecipes, {
|
||||
clearHistory: true,
|
||||
});
|
||||
},
|
||||
|
||||
// Calendar
|
||||
navigate(dir) {
|
||||
if (this.RTL) dir = !dir;
|
||||
let pv = this.plannerView;
|
||||
let date = new Date(this.year, this.month, this.date);
|
||||
let sd =
|
||||
pv == "mnth"
|
||||
? new Date(this.year, this.month + (dir ? 1 : 0), 0).getDate()
|
||||
: pv == "wk"
|
||||
? 7
|
||||
: 1;
|
||||
date.setDate(date.getDate() + (dir ? sd : -sd));
|
||||
this.date = date.getDate();
|
||||
this.month = date.getMonth();
|
||||
this.year = date.getFullYear();
|
||||
this.showBar();
|
||||
},
|
||||
goToToday() {
|
||||
let d = new Date();
|
||||
this.year = d.getFullYear();
|
||||
this.month = d.getMonth();
|
||||
this.date = d.getDate();
|
||||
this.showAppBar();
|
||||
},
|
||||
isToday(date) {
|
||||
let d = new Date();
|
||||
return (
|
||||
this.year == d.getFullYear() &&
|
||||
this.month == d.getMonth() &&
|
||||
date == d.getDate()
|
||||
);
|
||||
dayClasses({ d, m }) {
|
||||
let classes = "min ";
|
||||
let dt1 = new Date();
|
||||
let dt2 = new Date(this.year, m, d, 0).getTime();
|
||||
if (
|
||||
this.year == dt1.getFullYear() &&
|
||||
this.month == dt1.getMonth() &&
|
||||
m == dt1.getMonth() &&
|
||||
d == dt1.getDate()
|
||||
)
|
||||
classes += "tb ";
|
||||
classes += this.date == d && this.month == m ? "hl " : "fb ";
|
||||
if (!!this.mealPlans.filter((e) => e.date == dt2).length)
|
||||
classes += "accent ";
|
||||
if (this.month != m) classes += "sub";
|
||||
return classes;
|
||||
},
|
||||
isActive(date) {
|
||||
return this.date == date;
|
||||
},
|
||||
hasPlans(date) {
|
||||
let d = new Date(this.year, this.month, date, 0).getTime();
|
||||
return this.mealPlans.filter((e) => e.date == d).length;
|
||||
},
|
||||
setToday(date) {
|
||||
if (date) this.date = date;
|
||||
setDate({ d, m, y }) {
|
||||
this.year = y;
|
||||
this.month = m;
|
||||
this.date = d;
|
||||
this.showBar();
|
||||
},
|
||||
toggleEditMode() {
|
||||
this.edit = !this.edit;
|
||||
},
|
||||
openMonthYearPicker() {
|
||||
this.$showModal(MonthYearPicker, {
|
||||
this.$showModal(DMYPicker, {
|
||||
props: {
|
||||
title: "gtD",
|
||||
monthNames: this.mNames,
|
||||
monthNames: this.monthNames,
|
||||
currentD: this.date,
|
||||
currentM: this.month,
|
||||
currentY: this.year,
|
||||
},
|
||||
|
@ -355,69 +485,140 @@ export default {
|
|||
if (res) {
|
||||
this.month = res.month;
|
||||
this.year = res.year;
|
||||
this.date = res.date;
|
||||
}
|
||||
});
|
||||
},
|
||||
stSwipe({ direction }) {
|
||||
let date = new Date(this.year, this.month, this.date);
|
||||
if (direction == 1) date.setDate(date.getDate() - 1);
|
||||
else if (direction == 2) date.setDate(date.getDate() + 1);
|
||||
this.date = date.getDate();
|
||||
this.month = date.getMonth();
|
||||
this.year = date.getFullYear();
|
||||
},
|
||||
randomMealPlan() {},
|
||||
|
||||
// DATA HANDLERS
|
||||
newMealPlan({ date, type, title, index, inDB }) {
|
||||
// DataHandlers
|
||||
newMealPlan({ plan, index, inDB }) {
|
||||
this.addMealPlanAction({
|
||||
date: date ? date : this.todaysTime,
|
||||
type,
|
||||
title,
|
||||
plan,
|
||||
index,
|
||||
inDB,
|
||||
});
|
||||
},
|
||||
addRecipe(type) {
|
||||
let filteredRecipes = this.recipes.filter((e) =>
|
||||
this.getRecipes[type] ? !this.getRecipes[type].includes(e.id) : true
|
||||
);
|
||||
this.$showModal(ActionWithSearch, {
|
||||
addMealPlan() {
|
||||
this.$showModal(Action, {
|
||||
props: {
|
||||
title: "selRec",
|
||||
recipes: filteredRecipes,
|
||||
title: "add",
|
||||
list: ["rec", "no"],
|
||||
},
|
||||
}).then(
|
||||
(title) =>
|
||||
title &&
|
||||
this.newMealPlan({ date: 0, type, title, index: null, inDB: true })
|
||||
);
|
||||
}).then((type) => {
|
||||
if (type) {
|
||||
this.$showModal(Action, {
|
||||
props: {
|
||||
title: "selMT",
|
||||
list: ["breakfast", "lunch", "dinner", "snacks"],
|
||||
},
|
||||
}).then((mealType) => {
|
||||
if (mealType) {
|
||||
if (type == "rec") {
|
||||
let recipes = this.recipes.filter((e) =>
|
||||
this.getRecipes[mealType]
|
||||
? this.getRecipes[mealType].every((f) => f.recipeID != e.id)
|
||||
: 1
|
||||
);
|
||||
this.$showModal(ActionWithSearch, {
|
||||
props: {
|
||||
title: "selRec",
|
||||
recipes,
|
||||
action: "aNBtn",
|
||||
},
|
||||
}).then((res) => {
|
||||
if (res == "aNBtn") {
|
||||
this.$navigateTo(EditRecipe, {
|
||||
animated: false,
|
||||
});
|
||||
} else if (res) {
|
||||
let r = this.recipes.filter((e) => e.id == res)[0];
|
||||
this.$showModal(Prompt, {
|
||||
props: {
|
||||
title: `${localize("req", localize(r.yieldUnit))}`,
|
||||
placeholder: Math.abs(parseFloat(r.yieldQuantity)),
|
||||
action: "SET",
|
||||
},
|
||||
}).then((quantity) => {
|
||||
if (quantity) {
|
||||
let plan = {
|
||||
id: utils.getRandomID(),
|
||||
date: this.todaysTime,
|
||||
mealType,
|
||||
recipeID: res,
|
||||
quantity,
|
||||
note: null,
|
||||
};
|
||||
this.newMealPlan({
|
||||
plan,
|
||||
index: null,
|
||||
inDB: 1,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (type == "no") {
|
||||
this.$showModal(Prompt, {
|
||||
props: {
|
||||
title: "no",
|
||||
type: "view",
|
||||
action: "ADD",
|
||||
},
|
||||
}).then((note) => {
|
||||
if (note) {
|
||||
let plan = {
|
||||
id: utils.getRandomID(),
|
||||
date: this.todaysTime,
|
||||
mealType,
|
||||
recipeID: null,
|
||||
quantity: null,
|
||||
note,
|
||||
};
|
||||
this.newMealPlan({
|
||||
plan,
|
||||
index: null,
|
||||
inDB: 1,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
deleteTempFromDB() {
|
||||
if (this.temp) {
|
||||
this.temp.inDB = 1;
|
||||
this.deleteMealPlanAction(this.temp);
|
||||
let { plan, index } = this.temp;
|
||||
this.deleteMealPlanAction({ id: plan.id, index, inDB: 1 });
|
||||
this.temp = 0;
|
||||
}
|
||||
},
|
||||
removeRecipe(type, title) {
|
||||
removeRecipe(id) {
|
||||
this.deleteTempFromDB();
|
||||
let date = this.todaysTime;
|
||||
let index = this.mealPlans.findIndex(
|
||||
(e) => e.date == date && e.type == type && e.title == title
|
||||
);
|
||||
let mealPlan = {
|
||||
date,
|
||||
type,
|
||||
title,
|
||||
index,
|
||||
};
|
||||
let temp;
|
||||
this.temp = temp = mealPlan;
|
||||
this.deleteMealPlanAction(mealPlan);
|
||||
this.showUndoBar("recRm")
|
||||
.then(() => this.newMealPlan({ date, type, title, index }))
|
||||
let index = this.mealPlans.findIndex((e) => e.id == id);
|
||||
let plan = this.mealPlans.filter((e) => e.id == id)[0];
|
||||
this.temp = { plan, index };
|
||||
this.deleteMealPlanAction({ id, index });
|
||||
this.showUndoBar(plan.note ? "rmN" : "recRm")
|
||||
.then(() => this.newMealPlan({ plan, index }))
|
||||
.catch(() => {
|
||||
temp.inDB = 1;
|
||||
console.log("deleting inDB after catch: ", temp);
|
||||
this.deleteMealPlanAction(temp);
|
||||
this.deleteMealPlanAction({ id, index, inDB: 1 });
|
||||
});
|
||||
},
|
||||
showUndoBar(message) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.animateBar(this.appbar, 0).then(() => {
|
||||
this.showUndo = true;
|
||||
this.showUndo = 1;
|
||||
this.snackMsg = message;
|
||||
this.countdown = 5;
|
||||
this.animateBar(this.snackbar, 1).then(() => {
|
||||
|
@ -426,12 +627,12 @@ export default {
|
|||
barTimer = setInterval(() => {
|
||||
if (this.undo) {
|
||||
this.hideBar();
|
||||
resolve(true);
|
||||
resolve(1);
|
||||
}
|
||||
this.countdown = Math.round((a -= 0.1));
|
||||
if (this.countdown < 1) {
|
||||
this.hideBar();
|
||||
reject(true);
|
||||
reject(1);
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
|
@ -440,22 +641,76 @@ export default {
|
|||
},
|
||||
hideBar() {
|
||||
clearInterval(barTimer);
|
||||
this.deleteTempFromDB();
|
||||
this.animateBar(this.snackbar, 0).then(() => {
|
||||
this.showUndo = this.undo = false;
|
||||
this.showUndo = this.undo = 0;
|
||||
this.animateBar(this.appbar, 1);
|
||||
});
|
||||
},
|
||||
undoDel() {
|
||||
this.undo = true;
|
||||
this.undo = 1;
|
||||
},
|
||||
|
||||
//HELPERS
|
||||
touchMonthYearPicker({ object, action }) {
|
||||
object.className = action.match(/down|move/)
|
||||
? "monthName fade"
|
||||
: "monthName";
|
||||
// Helpers
|
||||
formattedDate(v) {
|
||||
let d = new Date(this.year, this.month, this.date, 0, 0, 0);
|
||||
let today = new Date();
|
||||
let myToday = new Date(
|
||||
today.getFullYear(),
|
||||
today.getMonth(),
|
||||
today.getDate(),
|
||||
0,
|
||||
0,
|
||||
0
|
||||
);
|
||||
let tdy = myToday.getTime();
|
||||
let ystr = myToday.setDate(today.getDate() - 1);
|
||||
let tmrw = myToday.setDate(today.getDate() + 1);
|
||||
let options: {
|
||||
year?: string;
|
||||
month?: string;
|
||||
weekday?: string;
|
||||
day?: string;
|
||||
} = {};
|
||||
if (v) {
|
||||
options.weekday = "long";
|
||||
options.day = "numeric";
|
||||
options.month = "long";
|
||||
} else {
|
||||
options.year = "numeric";
|
||||
options.month = "long";
|
||||
}
|
||||
if (this.plannerView == "d") {
|
||||
options.weekday = "long";
|
||||
options.day = "numeric";
|
||||
options.month = "short";
|
||||
}
|
||||
let date = new Intl.DateTimeFormat(null, options).format(d);
|
||||
let val;
|
||||
switch (d.getTime()) {
|
||||
case ystr:
|
||||
val = "ystr";
|
||||
break;
|
||||
case tdy:
|
||||
val = "tdy";
|
||||
break;
|
||||
case tmrw:
|
||||
val = "tmrw";
|
||||
break;
|
||||
}
|
||||
return v
|
||||
? [ystr, tdy, tmrw].some((e) => e == d.getTime())
|
||||
? localize(val)
|
||||
: date
|
||||
: date;
|
||||
},
|
||||
mYPicker({ object, action }) {
|
||||
object.className = action.match(/down|move/) ? "month fade" : "month";
|
||||
if (action == "up") this.openMonthYearPicker();
|
||||
},
|
||||
touchRecipe({ object, action }) {
|
||||
object.className = action.match(/down|move/) ? "fade" : "";
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,16 +1,21 @@
|
|||
<template>
|
||||
<Page @loaded="onPageLoad" @unloaded="onPageUnload" actionBarHidden="true">
|
||||
<GridLayout rows="*, auto" columns="*">
|
||||
<DockLayout stretchLastChild="true" rowSpan="2">
|
||||
<GridLayout
|
||||
<Page @loaded="pgLoad" @unloaded="onPageUnload" actionBarHidden="true">
|
||||
<GridLayout rows="*, auto, auto" columns="auto, *, auto">
|
||||
<DockLayout stretchLastChild="true" rowSpan="3" colSpan="3">
|
||||
<RGridLayout
|
||||
:rtl="RTL"
|
||||
dock="top"
|
||||
rows="auto,auto"
|
||||
columns="*, auto"
|
||||
paddingBottom="24"
|
||||
>
|
||||
<StackLayout>
|
||||
<Label class="pageTitle" paddingBottom="8" :text="recipe.title" />
|
||||
<StackLayout marginLeft="12" orientation="horizontal">
|
||||
<RLabel class="pageTitle" paddingBottom="8" :text="recipe.title" />
|
||||
<StackLayout
|
||||
:class="{ f: RTL }"
|
||||
margin="0 12"
|
||||
orientation="horizontal"
|
||||
>
|
||||
<Button
|
||||
class="ico rate"
|
||||
:class="{ rated: recipe.rating >= n }"
|
||||
|
@ -34,72 +39,82 @@
|
|||
decodeHeight="96"
|
||||
@tap="viewPhoto"
|
||||
/>
|
||||
</GridLayout>
|
||||
</RGridLayout>
|
||||
<AbsoluteLayout dock="bottom">
|
||||
<ScrollView
|
||||
dock="bottom"
|
||||
width="100%"
|
||||
height="100%"
|
||||
@loaded="onScrollLoad"
|
||||
@scroll="onScroll($event)"
|
||||
@scroll="svScroll($event)"
|
||||
>
|
||||
<StackLayout>
|
||||
<GridLayout rows="auto" columns="*, *">
|
||||
<RGridLayout :rtl="RTL" rows="auto" columns="*, *">
|
||||
<StackLayout class="attribute">
|
||||
<Label class="title sub" :text="'cui' | L" />
|
||||
<Label class="value" :text="recipe.cuisine | L" />
|
||||
<RLabel class="sub" :text="'cui' | L" />
|
||||
<RLabel class="value" :text="recipe.cuisine | L" />
|
||||
</StackLayout>
|
||||
<StackLayout class="attribute" col="1">
|
||||
<Label class="title sub" :text="'cat' | L" />
|
||||
<Label class="value" :text="recipe.category | L" />
|
||||
<RLabel class="sub" :text="'cat' | L" />
|
||||
<RLabel class="value" :text="recipe.category | L" />
|
||||
</StackLayout>
|
||||
</GridLayout>
|
||||
<StackLayout :hidden="!recipe.tags.length" class="attribute">
|
||||
<Label class="title sub" :text="'ts' | L" />
|
||||
<Label class="value" :text="getTags(recipe.tags)" />
|
||||
</RGridLayout>
|
||||
<StackLayout
|
||||
:hidden="!recipe.tags.length"
|
||||
class="attribute hal"
|
||||
:class="{ r: RTL }"
|
||||
>
|
||||
<RLabel class="sub" :text="'ts' | L" />
|
||||
<RLabel class="value" :text="getTags(recipe.tags)" />
|
||||
</StackLayout>
|
||||
<GridLayout rows="auto" columns="*, *">
|
||||
<RGridLayout :rtl="RTL" rows="auto" columns="*, *">
|
||||
<StackLayout
|
||||
class="attribute"
|
||||
:hidden="!hasTime(recipe.prepTime)"
|
||||
>
|
||||
<Label class="title sub" :text="'prepT' | L" />
|
||||
<Label class="value" :text="formattedTime(recipe.prepTime)" />
|
||||
<RLabel class="sub" :text="'prepT' | L" />
|
||||
<RLabel
|
||||
class="value"
|
||||
:text="formattedTime(recipe.prepTime)"
|
||||
/>
|
||||
</StackLayout>
|
||||
<StackLayout
|
||||
:col="hasTime(recipe.prepTime) ? 1 : 0"
|
||||
class="attribute"
|
||||
:hidden="!hasTime(recipe.cookTime)"
|
||||
>
|
||||
<Label class="title sub" :text="'cookT' | L" />
|
||||
<Label class="value" :text="formattedTime(recipe.cookTime)" />
|
||||
<RLabel class="title sub" :text="'cookT' | L" />
|
||||
<RLabel
|
||||
class="value"
|
||||
:text="formattedTime(recipe.cookTime)"
|
||||
/>
|
||||
</StackLayout>
|
||||
</GridLayout>
|
||||
<GridLayout rows="auto" columns="*, *">
|
||||
</RGridLayout>
|
||||
<RGridLayout :rtl="RTL" rows="auto" columns="*, *">
|
||||
<StackLayout class="attribute">
|
||||
<Label class="title sub" :text="'yld' | L" />
|
||||
<Label
|
||||
<RLabel class="title sub" :text="'yld' | L" />
|
||||
<RLabel
|
||||
@touch="touchYield"
|
||||
class="value clickable"
|
||||
horizontalAlignment="left"
|
||||
class="value accent"
|
||||
:text="`${tempYieldQuantity} ${$options.filters.L(
|
||||
recipe.yieldUnit
|
||||
)}`"
|
||||
/>
|
||||
</StackLayout>
|
||||
<StackLayout class="attribute" col="1">
|
||||
<Label class="title sub" :text="'Difficulty level' | L" />
|
||||
<Label class="value" :text="recipe.difficulty | L" />
|
||||
<RLabel class="title sub" :text="'Difficulty level' | L" />
|
||||
<RLabel class="value" :text="recipe.difficulty | L" />
|
||||
</StackLayout>
|
||||
</GridLayout>
|
||||
</RGridLayout>
|
||||
<StackLayout @loaded="onIngsLoad">
|
||||
<Label
|
||||
<RLabel
|
||||
padding="0 16"
|
||||
class="sectionTitle"
|
||||
:hidden="!recipe.ingredients.length"
|
||||
:text="getTitleCount('ings', 'ingredients')"
|
||||
/>
|
||||
<StackLayout
|
||||
<RStackLayout
|
||||
:rtl="RTL"
|
||||
orientation="horizontal"
|
||||
v-for="(item, index) in recipe.ingredients"
|
||||
:key="index + 'ing'"
|
||||
|
@ -107,39 +122,29 @@
|
|||
@touch="touchIngredient($event, index)"
|
||||
>
|
||||
<Button class="ico min" :text="icon.uncheck" />
|
||||
<Label
|
||||
class="value tw"
|
||||
:text="`${
|
||||
roundedQuantity(item.quantity)
|
||||
? roundedQuantity(item.quantity) + ' '
|
||||
: ''
|
||||
}${
|
||||
roundedQuantity(item.quantity)
|
||||
? $options.filters.L(item.unit) + ' '
|
||||
: ''
|
||||
}${item.item}`"
|
||||
/>
|
||||
</StackLayout>
|
||||
<RLabel class="value tw" :text="getIngredientItem(item)" />
|
||||
</RStackLayout>
|
||||
</StackLayout>
|
||||
<StackLayout @loaded="onInsLoad">
|
||||
<Label
|
||||
<RLabel
|
||||
padding="0 16"
|
||||
:hidden="!recipe.instructions.length"
|
||||
class="sectionTitle"
|
||||
:text="getTitleCount('inss', 'instructions')"
|
||||
/>
|
||||
<StackLayout
|
||||
<RStackLayout
|
||||
:rtl="RTL"
|
||||
orientation="horizontal"
|
||||
@touch="touchInstruction"
|
||||
v-for="(instruction, index) in recipe.instructions"
|
||||
:key="index + 'ins'"
|
||||
class="instruction"
|
||||
>
|
||||
<Button class="count ico min" :text="index + 1" />
|
||||
<Label class="value tw" :text="instruction" />
|
||||
</StackLayout>
|
||||
<Button class="count ico min" :text="getLocaleN(index + 1)" />
|
||||
<RLabel class="value tw" :text="instruction" />
|
||||
</RStackLayout>
|
||||
</StackLayout>
|
||||
<Label
|
||||
<RLabel
|
||||
@loaded="onCmbLoad"
|
||||
padding="0 16"
|
||||
:hidden="!recipe.combinations.length"
|
||||
|
@ -153,7 +158,7 @@
|
|||
:text="getCombinationTitle(combination)"
|
||||
@tap="viewCombination(combination)"
|
||||
/>
|
||||
<Label
|
||||
<RLabel
|
||||
@loaded="onNosTLoad"
|
||||
padding="0 16"
|
||||
:hidden="!recipe.notes.length"
|
||||
|
@ -161,17 +166,10 @@
|
|||
:text="getTitleCount('nos', 'notes')"
|
||||
/>
|
||||
<StackLayout @loaded="onNosLoad" padding="0 16"> </StackLayout>
|
||||
<Label
|
||||
class="dateInfo sub tw"
|
||||
:text="`${$options.filters.L('Last updated')}: ${formattedDate(
|
||||
recipe.lastModified
|
||||
)}\n${$options.filters.L('Created')}: ${formattedDate(
|
||||
recipe.created
|
||||
)}`"
|
||||
/>
|
||||
<Label class="dateInfo sub tw" :text="getDates().uc" />
|
||||
</StackLayout>
|
||||
</ScrollView>
|
||||
<Label
|
||||
<RLabel
|
||||
@loaded="onStickyLoad"
|
||||
class="sectionTitle sticky"
|
||||
:hidden="!stickyTitle"
|
||||
|
@ -181,61 +179,85 @@
|
|||
</DockLayout>
|
||||
<GridLayout
|
||||
row="1"
|
||||
@loaded="onAppBarLoad"
|
||||
class="appbar"
|
||||
v-show="!toast"
|
||||
columns="auto, *, auto, auto, auto, auto, auto"
|
||||
@loaded="sbload"
|
||||
class="appbar sidebar"
|
||||
:col="RTL ? 0 : 2"
|
||||
rows="auto, auto, auto"
|
||||
>
|
||||
<Button class="ico" :text="icon.timer" @tap="openCookingTimer" />
|
||||
<Button
|
||||
row="1"
|
||||
:hidden="busyDup"
|
||||
class="ico"
|
||||
:text="photoOpen ? icon.x : icon.back"
|
||||
@tap="navigateBack"
|
||||
:class="{ f: RTL }"
|
||||
:text="icon.dup"
|
||||
@tap="duplicateRecipe"
|
||||
/>
|
||||
<ActivityIndicator row="1" :hidden="!busyDup" :busy="busyDup" />
|
||||
<Button
|
||||
:hidden="!hasPrinterSupport"
|
||||
row="2"
|
||||
class="ico"
|
||||
:text="icon.print"
|
||||
@tap="printView"
|
||||
/>
|
||||
</GridLayout>
|
||||
<RGridLayout
|
||||
:rtl="RTL"
|
||||
row="2"
|
||||
colSpan="3"
|
||||
@loaded="abLoad"
|
||||
class="appbar"
|
||||
:hidden="toast"
|
||||
columns="auto, *, auto, auto, auto, auto"
|
||||
@touch="() => null"
|
||||
>
|
||||
<Button class="ico rtl" :text="icon.back" @tap="$navigateBack()" />
|
||||
<Button
|
||||
col="2"
|
||||
class="ico"
|
||||
:text="icon.timer"
|
||||
@tap="openCookingTimer"
|
||||
/>
|
||||
<Button
|
||||
col="3"
|
||||
v-if="!filterTrylater"
|
||||
class="ico"
|
||||
:text="recipe.tried ? icon.try : icon.tried"
|
||||
@tap="toggle('tried')"
|
||||
/>
|
||||
<Button
|
||||
col="3"
|
||||
col="2"
|
||||
v-else
|
||||
class="ico"
|
||||
:text="icon.done"
|
||||
@tap="toggle('tried', true)"
|
||||
@tap="toggle('tried', 1)"
|
||||
/>
|
||||
<Button
|
||||
col="4"
|
||||
col="3"
|
||||
class="ico"
|
||||
:text="recipe.favorite ? icon.faved : icon.fav"
|
||||
@tap="toggle('favorite')"
|
||||
/>
|
||||
<Button
|
||||
col="5"
|
||||
v-if="!busy"
|
||||
col="4"
|
||||
:hidden="busyEdit"
|
||||
class="ico"
|
||||
:text="icon.edit"
|
||||
@tap="editRecipe"
|
||||
/>
|
||||
<ActivityIndicator col="5" v-else :busy="busy" />
|
||||
<ActivityIndicator col="4" :hidden="!busyEdit" :busy="busyEdit" />
|
||||
<Button
|
||||
col="6"
|
||||
col="5"
|
||||
class="ico fab"
|
||||
:text="icon.share"
|
||||
@tap="shareHandler"
|
||||
/>
|
||||
</GridLayout>
|
||||
<Toast :toast="toast" :action="hideLastTried" />
|
||||
<AbsoluteLayout rowSpan="2">
|
||||
</RGridLayout>
|
||||
<Toast
|
||||
row="2"
|
||||
colSpan="3"
|
||||
:onload="tbLoad"
|
||||
:toast="toast"
|
||||
:action="hideBar"
|
||||
/>
|
||||
<AbsoluteLayout rowSpan="3" colSpan="3">
|
||||
<Image
|
||||
@tap="({ object }) => (object.cancel = true)"
|
||||
@tap="closePhoto"
|
||||
backgroundColor="black"
|
||||
stretch="aspectFit"
|
||||
@loaded="onImgViewLoad"
|
||||
|
@ -243,6 +265,7 @@
|
|||
class="photoviewer"
|
||||
/>
|
||||
</AbsoluteLayout>
|
||||
<WebView @loaded="wvLoad" hidden />
|
||||
</GridLayout>
|
||||
</Page>
|
||||
</template>
|
||||
|
@ -255,13 +278,13 @@ import {
|
|||
Utils,
|
||||
Span,
|
||||
FormattedString,
|
||||
Label,
|
||||
Observable,
|
||||
Screen,
|
||||
CoreTypes,
|
||||
WebView,
|
||||
} from "@nativescript/core";
|
||||
import { RLabel } from "~/rtl-ui";
|
||||
import { localize } from "@nativescript/localize";
|
||||
const intl = require("nativescript-intl");
|
||||
import { mapActions, mapState } from "vuex";
|
||||
import CookingTimer from "./CookingTimer.vue";
|
||||
import EditRecipe from "./EditRecipe.vue";
|
||||
|
@ -269,17 +292,24 @@ import Action from "./modals/Action.vue";
|
|||
import Toast from "./sub/Toast.vue";
|
||||
import Prompt from "./modals/Prompt.vue";
|
||||
import * as utils from "~/shared/utils";
|
||||
const Intl = require("nativescript-intl");
|
||||
let barTimer;
|
||||
declare const android: any;
|
||||
|
||||
export default {
|
||||
components: { Toast },
|
||||
props: ["filterTrylater", "recipeID"],
|
||||
props: ["filterTrylater", "recipeID", "yieldQuantity"],
|
||||
data() {
|
||||
return {
|
||||
busy: false,
|
||||
busyEdit: 0,
|
||||
busyDup: 0,
|
||||
yieldMultiplier: 1,
|
||||
recipe: null,
|
||||
currentRecipeID: this.recipeID,
|
||||
scrollview: null,
|
||||
appbar: null,
|
||||
sidebar: null,
|
||||
toastbar: null,
|
||||
ingcon: null,
|
||||
inscon: null,
|
||||
cmbcon: null,
|
||||
|
@ -290,13 +320,15 @@ export default {
|
|||
checked: 0,
|
||||
stepsDid: 0,
|
||||
toast: null,
|
||||
photoOpen: false,
|
||||
showTitleArr: [false, false, false, false],
|
||||
photoOpen: 0,
|
||||
showTitleArr: [0, 0, 0, 0],
|
||||
sticky: null,
|
||||
view: null,
|
||||
wv: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(["icon", "recipes"]),
|
||||
...mapState(["icon", "recipes", "RTL"]),
|
||||
tempYieldQuantity() {
|
||||
return Math.abs(this.yieldMultiplier) > 0
|
||||
? Math.abs(parseFloat(this.yieldMultiplier))
|
||||
|
@ -320,29 +352,38 @@ export default {
|
|||
}
|
||||
return val;
|
||||
},
|
||||
hasPrinterSupport() {
|
||||
return utils.Printer.isSupported();
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions([
|
||||
"toggleStateAction",
|
||||
"setComponent",
|
||||
"setRatingAction",
|
||||
"toggleCartAction",
|
||||
]),
|
||||
onPageLoad({ object }) {
|
||||
...mapActions(["toggleStateAction", "setRatingAction", "toggleCartAction"]),
|
||||
pgLoad({ object }) {
|
||||
this.busyDup = this.busyEdit = this.photoOpen = 0;
|
||||
object.bindingContext = new Observable();
|
||||
this.busy = this.photoOpen = false;
|
||||
this.setComponent("ViewRecipe");
|
||||
if (this.yieldMultiplier == this.recipe.yieldQuantity)
|
||||
this.yieldMultiplier = this.recipe.yieldQuantity;
|
||||
this.keepScreenOn(true);
|
||||
utils.keepScreenOn(1);
|
||||
this.syncCombinations();
|
||||
this.view = object.page.getViewById("printview");
|
||||
},
|
||||
onPageUnload() {
|
||||
this.keepScreenOn(false);
|
||||
utils.keepScreenOn(0);
|
||||
},
|
||||
onAppBarLoad({ object }) {
|
||||
sbload({ object }) {
|
||||
this.sidebar = object;
|
||||
},
|
||||
abLoad({ object }) {
|
||||
this.appbar = object;
|
||||
},
|
||||
tbLoad({ object }) {
|
||||
this.toastbar = object;
|
||||
this.recipe.tried && this.recipe.lastTried && this.showLastTried();
|
||||
},
|
||||
wvLoad({ object }) {
|
||||
this.wv = object;
|
||||
utils.updateLocale();
|
||||
},
|
||||
onIngsLoad({ object }) {
|
||||
this.ingcon = object;
|
||||
},
|
||||
|
@ -366,24 +407,22 @@ export default {
|
|||
this.imgView = object;
|
||||
this.imgView.visibility = "collapsed";
|
||||
this.imgView.top = 24;
|
||||
this.imgView.left = Screen.mainScreen.widthDIPs - 112;
|
||||
this.imgView.left = this.RTL ? 16 : Screen.mainScreen.widthDIPs - 112;
|
||||
},
|
||||
onStickyLoad({ object }) {
|
||||
this.sticky = object;
|
||||
},
|
||||
fixTitle({ object }, swipeUp: boolean): void {
|
||||
fixTitle(object, swipeUp: boolean): void {
|
||||
let ingL = this.recipe.ingredients.length;
|
||||
let insL = this.recipe.instructions.length;
|
||||
let cmbL = this.recipe.combinations.length;
|
||||
let notL = this.recipe.notes.length;
|
||||
|
||||
const isTop = (label): boolean => {
|
||||
let pos = label.getLocationRelativeTo(object).y;
|
||||
return label === this.cmbcon || label === this.notesT
|
||||
? pos < 0
|
||||
: pos + 32 < 0;
|
||||
};
|
||||
|
||||
const setVisibleTitle = (n: number): void => {
|
||||
let arr = [ingL, insL, cmbL, notL];
|
||||
this.showTitleArr = Array.from(
|
||||
|
@ -391,7 +430,6 @@ export default {
|
|||
(v, i) => (v = arr[i] ? i < n : false)
|
||||
);
|
||||
};
|
||||
|
||||
if (swipeUp) {
|
||||
if (ingL && !this.showTitleArr[0] && isTop(this.ingcon))
|
||||
setVisibleTitle(1);
|
||||
|
@ -412,45 +450,71 @@ export default {
|
|||
setVisibleTitle(0);
|
||||
}
|
||||
},
|
||||
onScroll(args) {
|
||||
svScroll({ object, scrollY }) {
|
||||
let swipeUp: boolean;
|
||||
let y = args.scrollY;
|
||||
let y = scrollY;
|
||||
if (y) {
|
||||
swipeUp = y > this.scrollPos;
|
||||
this.scrollPos = Math.abs(y);
|
||||
this.fixTitle(args, swipeUp);
|
||||
this.fixTitle(object, swipeUp);
|
||||
if (!this.toast) {
|
||||
let ab = this.appbar.translateY;
|
||||
if (swipeUp && ab == 0)
|
||||
this.appbar.animate({
|
||||
translate: { x: 0, y: 64 },
|
||||
duration: 250,
|
||||
curve: CoreTypes.AnimationCurve.ease,
|
||||
});
|
||||
else if (!swipeUp && ab == 64)
|
||||
this.appbar.animate({
|
||||
translate: { x: 0, y: 0 },
|
||||
duration: 250,
|
||||
curve: CoreTypes.AnimationCurve.ease,
|
||||
});
|
||||
if (swipeUp && ab == 0) this.hideBars();
|
||||
else if (!swipeUp && ab == 64) this.showBars();
|
||||
}
|
||||
}
|
||||
},
|
||||
// HELPERS
|
||||
showBars() {
|
||||
this.appbar.animate({
|
||||
translate: { x: 0, y: 0 },
|
||||
duration: 200,
|
||||
curve: CoreTypes.AnimationCurve.ease,
|
||||
});
|
||||
this.sidebar.animate({
|
||||
translate: { x: 0, y: 0 },
|
||||
duration: 200,
|
||||
curve: CoreTypes.AnimationCurve.ease,
|
||||
});
|
||||
},
|
||||
hideBars() {
|
||||
this.appbar.animate({
|
||||
translate: { x: 0, y: 64 },
|
||||
duration: 200,
|
||||
curve: CoreTypes.AnimationCurve.ease,
|
||||
});
|
||||
this.sidebar.animate({
|
||||
translate: { x: this.RTL ? -64 : 64, y: 0 },
|
||||
duration: 200,
|
||||
curve: CoreTypes.AnimationCurve.ease,
|
||||
});
|
||||
},
|
||||
|
||||
// Helpers
|
||||
getTitleCount(title, type) {
|
||||
let count = this.recipe[type].length;
|
||||
let selected = null;
|
||||
let c = this.recipe[type].length;
|
||||
let s = null;
|
||||
switch (title) {
|
||||
case "ings":
|
||||
selected = this.checked;
|
||||
s = this.checked;
|
||||
break;
|
||||
case "inss":
|
||||
selected = this.stepsDid;
|
||||
s = this.stepsDid;
|
||||
break;
|
||||
}
|
||||
let text = selected ? ` (${selected}/${count})` : ` (${count})`;
|
||||
c = this.getLocaleN(c);
|
||||
s = s && this.getLocaleN(s);
|
||||
let text = s ? ` (${s}/${c})` : ` (${c})`;
|
||||
return localize(title) + text;
|
||||
},
|
||||
getIngredientItem(item) {
|
||||
return `${
|
||||
this.roundedQuantity(item.quantity)
|
||||
? this.roundedQuantity(item.quantity) + " "
|
||||
: ""
|
||||
}${this.roundedQuantity(item.quantity) ? localize(item.unit) + " " : ""}${
|
||||
item.item
|
||||
}`;
|
||||
},
|
||||
changeYield() {
|
||||
this.$showModal(Prompt, {
|
||||
props: {
|
||||
|
@ -485,31 +549,25 @@ export default {
|
|||
);
|
||||
},
|
||||
showLastTried() {
|
||||
this.toast = localize("triedInfo", this.niceDate(this.recipe.lastTried));
|
||||
utils.timer(10, (val) => {
|
||||
if (!val) this.toast = val;
|
||||
this.animateBar(this.appbar, 0).then(() => {
|
||||
this.toast = localize(
|
||||
"triedInfo",
|
||||
this.niceDate(this.recipe.lastTried)
|
||||
);
|
||||
this.animateBar(this.toastbar, 1);
|
||||
let a = 10;
|
||||
clearInterval(barTimer);
|
||||
barTimer = setInterval(() => a-- < 1 && this.hideBar(), 1000);
|
||||
});
|
||||
},
|
||||
hideLastTried({ object }) {
|
||||
object
|
||||
.animate({
|
||||
opacity: 0,
|
||||
translate: { x: 0, y: 64 },
|
||||
duration: 250,
|
||||
curve: CoreTypes.AnimationCurve.ease,
|
||||
})
|
||||
.then(() => {
|
||||
this.showUndo = false;
|
||||
this.appbar.translateY = 64;
|
||||
this.appbar.animate({
|
||||
translate: { x: 0, y: 0 },
|
||||
duration: 250,
|
||||
curve: CoreTypes.AnimationCurve.ease,
|
||||
});
|
||||
object.opacity = 1;
|
||||
object.translateY = 0;
|
||||
this.toast = null;
|
||||
});
|
||||
hideBar() {
|
||||
clearInterval(barTimer);
|
||||
this.animateBar(this.toastbar, 0).then(() => {
|
||||
this.toast = null;
|
||||
this.photoOpen
|
||||
? (this.appbar.opacity = 1)
|
||||
: this.animateBar(this.appbar, 1);
|
||||
});
|
||||
},
|
||||
// getMeasure(value: number, unit: string) {
|
||||
// let vm = this;
|
||||
|
@ -560,14 +618,6 @@ export default {
|
|||
) / 100
|
||||
);
|
||||
},
|
||||
keepScreenOn(boolean) {
|
||||
let activity =
|
||||
Application.android.foregroundActivity ||
|
||||
Application.android.startActivity;
|
||||
let window = activity.getWindow();
|
||||
let flag = android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
|
||||
boolean ? window.addFlags(flag) : window.clearFlags(flag);
|
||||
},
|
||||
formattedTime(time) {
|
||||
let t = time.split(":");
|
||||
let h = parseInt(t[0]);
|
||||
|
@ -577,15 +627,13 @@ export default {
|
|||
return h ? (m ? `${h} ${hr} ${m} ${min}` : `${h} ${hr}`) : `${m} ${min}`;
|
||||
},
|
||||
formattedDate(date) {
|
||||
let d = new Date(date);
|
||||
var dateFormat = new intl.DateTimeFormat(null, {
|
||||
return new Intl.DateTimeFormat(null, {
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
hour: "numeric",
|
||||
minute: "numeric",
|
||||
}).format(d);
|
||||
return `${dateFormat}`;
|
||||
}).format(new Date(date));
|
||||
},
|
||||
isValidURL(string) {
|
||||
let pattern = new RegExp("^https?|^www", "ig");
|
||||
|
@ -654,26 +702,38 @@ export default {
|
|||
this.inscon.getChildAt(i).className = "instruction";
|
||||
}
|
||||
},
|
||||
getDates() {
|
||||
let u = `${localize("Last updated")}: ${this.formattedDate(
|
||||
this.recipe.lastModified
|
||||
)}`;
|
||||
let c = `${localize("Created")}: ${this.formattedDate(
|
||||
this.recipe.created
|
||||
)}`;
|
||||
return {
|
||||
u,
|
||||
c,
|
||||
uc: u + "\n" + c,
|
||||
};
|
||||
},
|
||||
|
||||
// NAVIGATION HANDLERS
|
||||
// NavigationHandlers
|
||||
editRecipe() {
|
||||
this.busy = true;
|
||||
this.busyEdit = 1;
|
||||
this.$navigateTo(EditRecipe, {
|
||||
props: {
|
||||
navigationFromView: true,
|
||||
filterTrylater: this.filterTrylater,
|
||||
recipeID: this.currentRecipeID,
|
||||
},
|
||||
// backstackVisible: false,
|
||||
animated: false,
|
||||
});
|
||||
},
|
||||
viewCombination(combination) {
|
||||
this.scrollview.scrollToVerticalOffset(0, true);
|
||||
this.recipe = this.recipes.filter((e) => e.id === combination)[0];
|
||||
this.showTitleArr = new Array(4).fill(false);
|
||||
this.showTitleArr = new Array(4).fill(0);
|
||||
this.clearChecks();
|
||||
this.clearSteps();
|
||||
this.recipe.ingredients.forEach(() => this.checks.push(false));
|
||||
this.recipe.ingredients.forEach(() => this.checks.push(0));
|
||||
this.currentRecipeID = combination;
|
||||
this.syncCombinations();
|
||||
this.createNotes();
|
||||
|
@ -681,7 +741,7 @@ export default {
|
|||
this.recipe.tried && this.recipe.lastTried && this.showLastTried();
|
||||
},
|
||||
|
||||
// SHARE ACTION
|
||||
// ShareAction
|
||||
shareHandler() {
|
||||
if (this.recipe.image) {
|
||||
this.$showModal(Action, {
|
||||
|
@ -696,7 +756,7 @@ export default {
|
|||
break;
|
||||
case "pht":
|
||||
ImageSource.fromFile(this.recipe.image).then((res) =>
|
||||
utils.shareImage(res, localize("srpu"))
|
||||
utils.shareImage(res, localize("srpu"), this.recipe.title)
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
@ -769,7 +829,7 @@ export default {
|
|||
utils.shareText(shareContent, localize("sru"));
|
||||
},
|
||||
|
||||
// DATA HANDLERS
|
||||
// DataHandlers
|
||||
toggle(key: string, setDate: boolean) {
|
||||
this.toggleStateAction({
|
||||
id: this.currentRecipeID,
|
||||
|
@ -787,7 +847,7 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
// SHOPPINGLIST
|
||||
// ShoppingList
|
||||
toggleCart() {
|
||||
if (!this.recipe.inBag) {
|
||||
} else {
|
||||
|
@ -797,10 +857,10 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
// NOTES
|
||||
// Notes
|
||||
createNote(note) {
|
||||
let regex = /(https?:\/\/[^\s]+)/g;
|
||||
const lbl = new Label();
|
||||
const lbl = new RLabel();
|
||||
lbl.className = "note";
|
||||
lbl.textWrap = true;
|
||||
let fString = new FormattedString();
|
||||
|
@ -851,7 +911,8 @@ export default {
|
|||
} else this.$navigateBack();
|
||||
},
|
||||
viewPhoto() {
|
||||
this.photoOpen = true;
|
||||
this.hideBars();
|
||||
this.photoOpen = 1;
|
||||
this.hijackBackEvent();
|
||||
let pv = this.imgView;
|
||||
pv.visibility = "visible";
|
||||
|
@ -865,16 +926,16 @@ export default {
|
|||
pv.animate({
|
||||
width: sw,
|
||||
height: sw,
|
||||
translate: { x: 112 - sw, y: (sh - sw) / 3 },
|
||||
duration: 250,
|
||||
translate: { x: this.RTL ? -16 : 112 - sw, y: (sh - sw) / 3 },
|
||||
duration: 200,
|
||||
curve: CoreTypes.AnimationCurve.ease,
|
||||
})
|
||||
)
|
||||
.then(() =>
|
||||
pv.animate({
|
||||
height: sh,
|
||||
translate: { x: -sw + 112, y: -((sh - sw) / 6) },
|
||||
duration: 250,
|
||||
translate: { x: this.RTL ? -16 : 112 - sw, y: -((sh - sw) / 6) },
|
||||
duration: 200,
|
||||
curve: CoreTypes.AnimationCurve.ease,
|
||||
})
|
||||
);
|
||||
|
@ -886,8 +947,8 @@ export default {
|
|||
pv.animate({
|
||||
width: sw,
|
||||
height: sw,
|
||||
translate: { x: 112 - sw, y: (sh - sw) / 3 },
|
||||
duration: 250,
|
||||
translate: { x: this.RTL ? -16 : 112 - sw, y: (sh - sw) / 3 },
|
||||
duration: 200,
|
||||
curve: CoreTypes.AnimationCurve.ease,
|
||||
})
|
||||
.then(() =>
|
||||
|
@ -895,7 +956,7 @@ export default {
|
|||
width: 96,
|
||||
height: 96,
|
||||
translate: { x: 0, y: 0 },
|
||||
duration: 250,
|
||||
duration: 200,
|
||||
curve: CoreTypes.AnimationCurve.ease,
|
||||
})
|
||||
)
|
||||
|
@ -907,37 +968,162 @@ export default {
|
|||
)
|
||||
.then(() => {
|
||||
pv.visibility = "collapsed";
|
||||
this.photoOpen = false;
|
||||
this.photoOpen = 0;
|
||||
this.releaseBackEvent();
|
||||
this.showBars();
|
||||
});
|
||||
},
|
||||
navigateBack() {
|
||||
this.photoOpen ? this.closePhoto() : this.$navigateBack();
|
||||
},
|
||||
|
||||
//TIMERS
|
||||
// Timers
|
||||
openCookingTimer() {
|
||||
this.$navigateTo(CookingTimer, {
|
||||
props: {
|
||||
recipeID: this.recipe.id,
|
||||
},
|
||||
animated: false,
|
||||
});
|
||||
},
|
||||
//HELPERS
|
||||
|
||||
//DuplicateRecipe
|
||||
duplicateRecipe() {
|
||||
this.busyDup = 1;
|
||||
let dupRecipe = Object.assign({}, this.recipe);
|
||||
dupRecipe.id = utils.getRandomID(0);
|
||||
dupRecipe.title = dupRecipe.title + " " + localize("cpy");
|
||||
this.$navigateTo(EditRecipe, {
|
||||
props: {
|
||||
dupRecipe,
|
||||
},
|
||||
animated: false,
|
||||
});
|
||||
},
|
||||
|
||||
// Print
|
||||
prepareHTML() {
|
||||
let r = this.recipe;
|
||||
const head = `<head><meta charset=UTF-8><meta content="IE=edge"http-equiv=X-UA-Compatible><meta content="width=device-width,initial-scale=1"name=viewport><title>EnRecipes - Recipe for Print</title><style>a,body,div,html,img,ol,p,span,ul{border:0;font-size:100%;font:inherit;margin:0;padding:0;vertical-align:baseline}@font-face{font-family:Inter-Medium;src:url(../app/fonts/Inter-Medium.otf)}@font-face{font-family:Inter-Bold;src:url(../app/fonts/Inter-Bold.otf)}body{font-family:Inter-Medium,sans-serif;line-height:1.5;max-width:45rem;padding:1.5rem}body>p{padding:.5rem 0}.attr>div>p:last-child,h1,h2{font-family:Inter-Bold,sans-serif}#header{display:grid;grid-column-gap:2rem;grid-template-columns:1fr auto;margin-bottom:2.5rem;width:100%}img{border-radius:1rem;height:8rem;object-fit:cover;width:8rem}h1{font-size:2.25rem;line-height:1.25;margin:0;padding-bottom:1rem}svg{width:2rem;height:2rem;padding:0 .5rem 0 0}h2{margin:2rem 0 1rem}.attr{display:grid;grid-column-gap:2rem;grid-template-columns:1fr 1fr;margin-top:1rem}.attr>div>p:first-child{font-size:.9rem;opacity:.5}ol,ul{padding:0 1.5rem}li{padding:.5rem}a{color:inherit}.sub{font-size:.9rem;margin-top:2rem;opacity:.5}</style></head>`;
|
||||
const getStarRating = () => {
|
||||
let rate = `<svg width="100%" height="100%" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2"><path d="M10.756 2.826 8.419 7.98l-5.624.63c-.533.06-.982.425-1.147.935-.166.51-.018 1.07.378 1.431l4.179 3.816-1.138 5.543c-.108.525.101 1.065.535 1.38.434.315 1.012.348 1.478.083L12 19.002l4.92 2.796c.466.265 1.044.232 1.478-.083.434-.315.643-.855.535-1.38l-1.138-5.543 4.179-3.816c.396-.361.544-.921.378-1.431-.165-.51-.614-.875-1.147-.935l-5.624-.63-2.337-5.154c-.221-.489-.708-.802-1.244-.802s-1.023.313-1.244.802z"/></svg>`;
|
||||
let unrate = `<svg width="100%" height="100%" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2"><path d="M10.756 2.826 8.419 7.98l-5.624.63c-.533.06-.982.425-1.147.935-.166.51-.018 1.07.378 1.431l4.179 3.816-1.138 5.543c-.108.525.101 1.065.535 1.38.434.315 1.012.348 1.478.083L12 19.002l4.92 2.796c.466.265 1.044.232 1.478-.083.434-.315.643-.855.535-1.38l-1.138-5.543 4.179-3.816c.396-.361.544-.921.378-1.431-.165-.51-.614-.875-1.147-.935l-5.624-.63-2.337-5.154c-.221-.489-.708-.802-1.244-.802s-1.023.313-1.244.802zM12 4.925l1.994 4.398c.146.321.45.542.8.581l4.799.538-3.567 3.256c-.26.237-.376.594-.305.94l.972 4.73-4.199-2.386c-.306-.174-.682-.174-.988.0l-4.199 2.386.972-4.73c.071-.346-.045-.703-.305-.94l-3.567-3.256 4.799-.538c.35-.039.654-.26.8-.581L12 4.925z"/></svg>`;
|
||||
return rate.repeat(r.rating) + unrate.repeat(5 - r.rating);
|
||||
};
|
||||
const img = r.image ? `<img src="${r.image}" alt="${r.title}" />` : "";
|
||||
const getIngs = () => {
|
||||
let ing = [];
|
||||
r.ingredients.forEach((e) => {
|
||||
ing.push(`<li>${this.getIngredientItem(e)}</li>`);
|
||||
});
|
||||
return ing.join("");
|
||||
};
|
||||
const getIns = () => {
|
||||
let ins = [];
|
||||
r.instructions.forEach((e) => {
|
||||
ins.push(`<li>${e}</li>`);
|
||||
});
|
||||
return ins.join("");
|
||||
};
|
||||
const getCmbs = () => {
|
||||
let cmb = [];
|
||||
r.combinations.forEach((e) => {
|
||||
cmb.push(`<p>${this.getCombinationTitle(e)}</p>`);
|
||||
});
|
||||
return cmb.join("");
|
||||
};
|
||||
const getNotes = () => {
|
||||
let regex = /(https?:\/\/[^\s]+)/g;
|
||||
let n = [];
|
||||
const createSpan = (val, isUrl) => {
|
||||
return isUrl
|
||||
? `<a href="${val}" target="_blank" rel="noopener noreferrer">${val}</a>`
|
||||
: val;
|
||||
};
|
||||
r.notes.forEach((e) => {
|
||||
let arr = e.split(regex);
|
||||
let single = [];
|
||||
arr.forEach((f) => {
|
||||
single.push(createSpan(f, regex.test(f)));
|
||||
});
|
||||
n.push(`<p>${single.join("")}</p>`);
|
||||
});
|
||||
return n.join("");
|
||||
};
|
||||
return `<html dir="${
|
||||
this.RTL ? "rtl" : "ltr"
|
||||
}">${head}<body><div id=header><div class=title><h1>${
|
||||
r.title
|
||||
}</h1><div class=rating>${getStarRating()}</div></div>${img}</div><div class=attr><div><p>${localize(
|
||||
"cui"
|
||||
)}<p>${r.cuisine}</div><div><p>${localize("cat")}<p>${
|
||||
r.category
|
||||
}</div></div>${
|
||||
r.tags.length
|
||||
? `<div class=attr><div style="grid-column:span 2"><p>${localize(
|
||||
"ts"
|
||||
)}<p>${this.getTags(r.tags)}</div></div>`
|
||||
: ""
|
||||
} ${
|
||||
this.hasTime(r.prepTime) || this.hasTime(r.cookTime)
|
||||
? `<div class=attr>${
|
||||
this.hasTime(r.prepTime)
|
||||
? `<div><p>${localize("prepT")}<p>${this.formattedTime(
|
||||
r.prepTime
|
||||
)}</div>`
|
||||
: ""
|
||||
} ${
|
||||
this.hasTime(r.cookTime)
|
||||
? `<div><p>${localize("cookT")}<p>${this.formattedTime(
|
||||
r.cookTime
|
||||
)}</div>`
|
||||
: ""
|
||||
}</div>`
|
||||
: ""
|
||||
}<div class=attr><div><p>${localize("yld")}<p>${
|
||||
this.tempYieldQuantity
|
||||
} ${localize(r.yieldUnit)}</div><div><p>${localize(
|
||||
"Difficulty level"
|
||||
)}<p>${r.difficulty}</div></div>${
|
||||
r.ingredients.length
|
||||
? `<h2>${this.getTitleCount("ings", "ingredients")}</h2>`
|
||||
: ""
|
||||
}<ul>${getIngs()}</ul>${
|
||||
r.instructions.length
|
||||
? `<h2>${this.getTitleCount("inss", "instructions")}</h2>`
|
||||
: ""
|
||||
}<ol>${getIns()}</ol>${
|
||||
r.combinations.length
|
||||
? `<h2>${this.getTitleCount("cmbs", "combinations")}</h2>`
|
||||
: ""
|
||||
} ${getCmbs()} ${
|
||||
r.notes.length ? `<h2>${this.getTitleCount("nos", "notes")}</h2>` : ""
|
||||
} ${getNotes()}<div class=sub><p>${this.getDates().u}<p>${
|
||||
this.getDates().c
|
||||
}</div>
|
||||
</body>
|
||||
</html>`;
|
||||
},
|
||||
printView() {
|
||||
let wv = this.wv as WebView;
|
||||
const fileName = `${this.recipe.title} - ${localize("EnRecipes")}`;
|
||||
wv.src = this.prepareHTML();
|
||||
wv.once("loadFinished", () =>
|
||||
utils.Printer.print(wv, fileName).then(() => (wv.src = null))
|
||||
);
|
||||
},
|
||||
|
||||
// Helpers
|
||||
touchYield({ object, action }) {
|
||||
object.className = action.match(/down|move/)
|
||||
? "value clickable fade"
|
||||
: "value clickable";
|
||||
? "value accent fade"
|
||||
: "value accent";
|
||||
if (action == "up") this.changeYield();
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.recipe = this.recipes.filter((e) => e.id === this.currentRecipeID)[0];
|
||||
this.recipe.ingredients.forEach((e) => this.checks.push(false));
|
||||
this.recipe.ingredients.forEach((e) => this.checks.push(0));
|
||||
},
|
||||
mounted() {
|
||||
this.yieldMultiplier = this.recipe.yieldQuantity;
|
||||
this.recipe.tried && this.recipe.lastTried && this.showLastTried();
|
||||
this.yieldMultiplier = this.yieldQuantity || this.recipe.yieldQuantity;
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
<Page
|
||||
@loaded="transparentPage"
|
||||
backgroundColor="transparent"
|
||||
:class="appTheme"
|
||||
:class="theme"
|
||||
>
|
||||
<GridLayout
|
||||
columns="*"
|
||||
:rows="`auto, auto, ${stretch ? '*' : 'auto'}, auto`"
|
||||
class="modal"
|
||||
>
|
||||
<Label class="title" :text="title | L" />
|
||||
<RLabel class="title" :text="title | L" />
|
||||
<ListView
|
||||
rowHeight="48"
|
||||
row="2"
|
||||
|
@ -17,10 +17,9 @@
|
|||
:height="stretch ? '100%' : listHeight"
|
||||
>
|
||||
<v-template>
|
||||
<Label
|
||||
<RLabel
|
||||
class="listItem"
|
||||
:class="{ tb: title === 'srt' && sortType === item }"
|
||||
:color="title === 'srt' && sortType === item ? '#ff5200' : ''"
|
||||
:class="{ select: item == selected || $index == selected }"
|
||||
:text="`${localized(item)}`"
|
||||
@touch="touch"
|
||||
@tap="tapAction(item)"
|
||||
|
@ -28,9 +27,9 @@
|
|||
/>
|
||||
</v-template>
|
||||
</ListView>
|
||||
<GridLayout row="3" columns="auto, *, auto" class="actions">
|
||||
<RGridLayout :rtl="RTL" row="3" columns="auto, *, auto" class="actions">
|
||||
<Button
|
||||
v-if="action"
|
||||
:hidden="!action"
|
||||
class="text sm"
|
||||
:text="action | L"
|
||||
@tap="$modal.close(action)"
|
||||
|
@ -39,9 +38,9 @@
|
|||
col="2"
|
||||
class="text sm"
|
||||
:text="'cBtn' | L"
|
||||
@tap="$modal.close(false)"
|
||||
@tap="$modal.close(0)"
|
||||
/>
|
||||
</GridLayout>
|
||||
</RGridLayout>
|
||||
</GridLayout>
|
||||
</Page>
|
||||
</template>
|
||||
|
@ -54,7 +53,7 @@ import Confirm from "./Confirm.vue";
|
|||
|
||||
interface IData {
|
||||
newList: unknown[];
|
||||
stretch: boolean;
|
||||
stretch: number;
|
||||
listHeight: number;
|
||||
}
|
||||
|
||||
|
@ -72,26 +71,30 @@ export default {
|
|||
type: String,
|
||||
required: false,
|
||||
},
|
||||
selected: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
data(): IData {
|
||||
return {
|
||||
newList: this.list,
|
||||
stretch: false,
|
||||
stretch: 0,
|
||||
listHeight: 0,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(["sortType", "icon", "appTheme"]),
|
||||
...mapState(["sortType", "icon", "theme", "RTL"]),
|
||||
},
|
||||
methods: {
|
||||
...mapActions(["removeListItemAction"]),
|
||||
...mapActions(["removeListItemAction", "deleteTimerPreset"]),
|
||||
localized(item: string): string {
|
||||
return this.title !== "lang" ? localize(item) : item;
|
||||
},
|
||||
tapAction(item: string): void {
|
||||
this.$modal.close(item);
|
||||
},
|
||||
deletionConfirmation(description: string): void {
|
||||
removeConfirmation(description: string): void {
|
||||
return this.$showModal(Confirm, {
|
||||
props: {
|
||||
title: "conf",
|
||||
|
@ -101,13 +104,24 @@ export default {
|
|||
},
|
||||
});
|
||||
},
|
||||
deletionConfirmation(description: string): void {
|
||||
return this.$showModal(Confirm, {
|
||||
props: {
|
||||
title: "conf",
|
||||
description,
|
||||
cancelButtonText: "cBtn",
|
||||
okButtonText: "dBtn",
|
||||
},
|
||||
});
|
||||
},
|
||||
removeItem(item: string): void {
|
||||
let vm = this;
|
||||
let index = this.newList.findIndex((e) => e === item);
|
||||
let localizedItem = `"${localize(item)}"`;
|
||||
function removeListItem(listName: string, desc: string): void {
|
||||
vm.deletionConfirmation(`${localize(desc, localizedItem)}`).then(
|
||||
vm.removeConfirmation(`${localize(desc, localizedItem)}`).then(
|
||||
(action: boolean) => {
|
||||
if (action != null && action)
|
||||
if (action)
|
||||
vm.removeListItemAction({
|
||||
item,
|
||||
listName,
|
||||
|
@ -115,6 +129,16 @@ export default {
|
|||
}
|
||||
);
|
||||
}
|
||||
function deleteTimerPreset(): void {
|
||||
vm.deletionConfirmation(`${localize("delPrst", `"${item}"`)}`).then(
|
||||
(action: boolean) => {
|
||||
if (action) {
|
||||
vm.deleteTimerPreset(index);
|
||||
vm.newList.splice(index, 1);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
switch (this.title) {
|
||||
case "cui":
|
||||
removeListItem("cuisines", "rmCuiInfo");
|
||||
|
@ -128,12 +152,18 @@ export default {
|
|||
case "Unit":
|
||||
removeListItem("units", "rmUInfo");
|
||||
break;
|
||||
case "prsts":
|
||||
deleteTimerPreset();
|
||||
break;
|
||||
}
|
||||
},
|
||||
touch({ object, action }): void {
|
||||
let classes = object.className;
|
||||
object.className = action.match(/down|move/)
|
||||
? "listItem fade"
|
||||
: "listItem";
|
||||
? !classes.includes("fade")
|
||||
? classes + " fade"
|
||||
: classes
|
||||
: classes.replace(/ fade/g, "");
|
||||
},
|
||||
},
|
||||
created() {
|
||||
|
@ -145,7 +175,7 @@ export default {
|
|||
if (modalHeight < usableHeight) {
|
||||
this.listHeight = listHeight;
|
||||
} else {
|
||||
this.stretch = true;
|
||||
this.stretch = 1;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -2,20 +2,25 @@
|
|||
<Page
|
||||
@loaded="transparentPage"
|
||||
backgroundColor="transparent"
|
||||
:class="appTheme"
|
||||
:class="theme"
|
||||
>
|
||||
<GridLayout columns="*" rows="auto, auto, *, auto" class="modal">
|
||||
<Label class="title" :text="title | L" />
|
||||
<RLabel class="title" :text="title | L" />
|
||||
<StackLayout
|
||||
row="1"
|
||||
v-if="filteredRecipes.length || searchQuery"
|
||||
:hidden="!filteredRecipes.length && !searchQuery"
|
||||
class="input"
|
||||
>
|
||||
<TextField class="modalInput" :hint="'ser' | L" v-model="searchQuery" />
|
||||
<TextField
|
||||
@loaded="setGravity"
|
||||
class="modalInput"
|
||||
:hint="'ser' | L"
|
||||
v-model="searchQuery"
|
||||
/>
|
||||
</StackLayout>
|
||||
<ListView row="2" for="recipe in filteredRecipes">
|
||||
<v-template>
|
||||
<Label
|
||||
<RLabel
|
||||
class="listItem"
|
||||
:text="recipe.title"
|
||||
@touch="touch($event, recipe)"
|
||||
|
@ -25,18 +30,18 @@
|
|||
<Label
|
||||
row="2"
|
||||
class="noResInfo"
|
||||
v-if="!filteredRecipes.length && !searchQuery"
|
||||
:hidden="recipes.length"
|
||||
:text="'recListEmp' | L"
|
||||
/>
|
||||
<Label
|
||||
row="2"
|
||||
class="noResInfo"
|
||||
v-if="!filteredRecipes.length && searchQuery"
|
||||
:hidden="filteredRecipes.length || !searchQuery"
|
||||
:text="'noRecs' | L"
|
||||
/>
|
||||
<GridLayout row="3" columns="auto, *, auto" class="actions">
|
||||
<RGridLayout :rtl="RTL" row="3" columns="auto, *, auto" class="actions">
|
||||
<Button
|
||||
v-if="action"
|
||||
:hidden="!action"
|
||||
class="text sm"
|
||||
:text="action | L"
|
||||
@tap="$modal.close(action)"
|
||||
|
@ -45,9 +50,9 @@
|
|||
col="2"
|
||||
class="text sm"
|
||||
:text="'cBtn' | L"
|
||||
@tap="$modal.close(false)"
|
||||
@tap="$modal.close(0)"
|
||||
/>
|
||||
</GridLayout>
|
||||
</RGridLayout>
|
||||
</GridLayout>
|
||||
</Page>
|
||||
</template>
|
||||
|
@ -62,7 +67,7 @@ export default {
|
|||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(["icon", "appTheme"]),
|
||||
...mapState(["icon", "theme", "RTL"]),
|
||||
filteredRecipes() {
|
||||
return this.recipes
|
||||
.map((e, i) => {
|
||||
|
@ -82,8 +87,8 @@ export default {
|
|||
tapAction(recipe) {
|
||||
this.$modal.close(recipe.id);
|
||||
},
|
||||
centerLabel(args) {
|
||||
args.object.android.setGravity(16);
|
||||
centerLabel({ object }) {
|
||||
object.android.setGravity(16);
|
||||
},
|
||||
recipeFilter(e) {
|
||||
let searchQuery = this.searchQuery.toLowerCase();
|
||||
|
@ -98,7 +103,7 @@ export default {
|
|||
touch({ object, action }, recipe) {
|
||||
object.className = action.match(/down|move/)
|
||||
? "listItem fade"
|
||||
: "listItem";
|
||||
: "listItem ";
|
||||
if (action == "up") this.tapAction(recipe);
|
||||
},
|
||||
},
|
||||
|
|
|
@ -2,31 +2,31 @@
|
|||
<Page
|
||||
@loaded="transparentPage"
|
||||
backgroundColor="transparent"
|
||||
:class="appTheme"
|
||||
:class="theme"
|
||||
>
|
||||
<GridLayout rows="auto, auto, auto" class="modal">
|
||||
<Label class="title" :text="title | L" />
|
||||
<RLabel class="title" :text="title | L" />
|
||||
<Label
|
||||
row="1"
|
||||
v-if="description"
|
||||
class="description tw"
|
||||
:text="description"
|
||||
/>
|
||||
<GridLayout row="2" columns="*, auto, auto" class="actions">
|
||||
<RGridLayout :rtl="RTL" row="2" columns="*, auto, auto" class="actions">
|
||||
<Button
|
||||
v-if="cancelButtonText"
|
||||
col="1"
|
||||
class="text sm"
|
||||
:text="cancelButtonText | L"
|
||||
@tap="$modal.close(false)"
|
||||
@tap="$modal.close(0)"
|
||||
/>
|
||||
<Button
|
||||
col="2"
|
||||
class="text sm"
|
||||
:text="okButtonText | L"
|
||||
@tap="$modal.close(true)"
|
||||
@tap="$modal.close(1)"
|
||||
/>
|
||||
</GridLayout>
|
||||
</RGridLayout>
|
||||
</GridLayout>
|
||||
</Page>
|
||||
</template>
|
||||
|
@ -53,7 +53,7 @@ export default {
|
|||
},
|
||||
},
|
||||
computed: {
|
||||
...mapState(["icon", "appTheme"]),
|
||||
...mapState(["icon", "theme", "RTL"]),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
108
app/components/modals/DMYPicker.vue
Normal file
|
@ -0,0 +1,108 @@
|
|||
<template>
|
||||
<Page
|
||||
@loaded="transparentPage"
|
||||
backgroundColor="transparent"
|
||||
:class="theme"
|
||||
>
|
||||
<GridLayout rows="auto, auto, auto" class="modal">
|
||||
<RLabel class="title" :text="title | L" />
|
||||
<RStackLayout
|
||||
:rtl="RTL"
|
||||
row="1"
|
||||
orientation="horizontal"
|
||||
horizontalAlignment="center"
|
||||
>
|
||||
<ListPicker
|
||||
@loaded="onLPLoad"
|
||||
:items="days"
|
||||
:selectedIndex="dIndex"
|
||||
@selectedIndexChange="setD"
|
||||
></ListPicker>
|
||||
<ListPicker
|
||||
@loaded="onLPLoad"
|
||||
:items="months"
|
||||
:selectedIndex="currentM"
|
||||
@selectedIndexChange="setM"
|
||||
></ListPicker>
|
||||
<ListPicker
|
||||
:items="years"
|
||||
:selectedIndex="yIndex"
|
||||
@selectedIndexChange="setY"
|
||||
></ListPicker>
|
||||
</RStackLayout>
|
||||
<RGridLayout :rtl="RTL" row="2" columns="*, auto, auto" class="actions">
|
||||
<Button
|
||||
col="1"
|
||||
class="text sm"
|
||||
:text="'cBtn' | L"
|
||||
@tap="$modal.close(0)"
|
||||
/>
|
||||
<Button
|
||||
col="2"
|
||||
class="text sm"
|
||||
:text="'SET' | L"
|
||||
@tap="$modal.close(selected)"
|
||||
/>
|
||||
</RGridLayout>
|
||||
</GridLayout>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from "vuex";
|
||||
import { localize } from "@nativescript/localize";
|
||||
export default {
|
||||
props: ["title", "monthNames", "currentD", "currentM", "currentY"],
|
||||
data() {
|
||||
return {
|
||||
selectedD: 0,
|
||||
selectedM: 0,
|
||||
selectedY: 0,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(["icon", "theme", "RTL"]),
|
||||
days() {
|
||||
let ld = new Date(this.selectedY, this.selectedM + 1, 0).getDate();
|
||||
return Array.from({ length: ld }, (v, i) => i + 1);
|
||||
},
|
||||
dIndex() {
|
||||
return this.days.indexOf(this.selectedD || this.currentD);
|
||||
},
|
||||
months() {
|
||||
return this.monthNames.map((e) => localize(e));
|
||||
},
|
||||
years() {
|
||||
let min = 1900;
|
||||
let max = min + 200;
|
||||
let years = [];
|
||||
for (let i = min; i <= max; i++) years.push(i);
|
||||
return years;
|
||||
},
|
||||
yIndex() {
|
||||
return this.years.indexOf(this.currentY);
|
||||
},
|
||||
selected() {
|
||||
return {
|
||||
date: this.selectedD,
|
||||
month: this.selectedM,
|
||||
year: this.selectedY,
|
||||
};
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onLPLoad({ object }) {
|
||||
object.android.setWrapSelectorWheel(true);
|
||||
},
|
||||
setD(args) {
|
||||
this.selectedD = args.object.selectedIndex + 1;
|
||||
},
|
||||
setM(args) {
|
||||
this.selectedM = args.object.selectedIndex;
|
||||
},
|
||||
setY(args) {
|
||||
this.selectedY = this.years[args.object.selectedIndex];
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
|
@ -1,28 +1,32 @@
|
|||
<template>
|
||||
<Page @loaded="onPageLoad" backgroundColor="transparent" :class="appTheme">
|
||||
<Page @loaded="pgLoad" backgroundColor="transparent" :class="theme">
|
||||
<GridLayout rows="auto, auto, *, auto" columns="*" class="modal">
|
||||
<Label class="title" :text="`fltr` | L" />
|
||||
<RLabel class="title a" :text="`fltr` | L" />
|
||||
<ScrollView orientation="horizontal" row="1" @loaded="onScrollLoad">
|
||||
<StackLayout class="filters" orientation="horizontal">
|
||||
<RStackLayout :rtl="RTL" class="filters" orientation="horizontal">
|
||||
<GridLayout
|
||||
rows="48"
|
||||
columns="auto, auto"
|
||||
class="segment"
|
||||
class="segment rtl"
|
||||
v-for="(item, index) in pathList"
|
||||
:key="index"
|
||||
:class="{
|
||||
select: filterType === item.type,
|
||||
}"
|
||||
:class="{ select: filterType === item.type }"
|
||||
@touch="touchSelector($event, item.type)"
|
||||
>
|
||||
<Label class="ico" :text="icon[item.type]" />
|
||||
<Label v-if="item.title" class="value" :text="item.title" col="1" />
|
||||
<Label
|
||||
:hidden="!item.title"
|
||||
class="value"
|
||||
:class="{ r: RTL }"
|
||||
:text="item.title"
|
||||
col="1"
|
||||
/>
|
||||
</GridLayout>
|
||||
</StackLayout>
|
||||
</RStackLayout>
|
||||
</ScrollView>
|
||||
<ListView row="2" class="options-list" for="item in filterList">
|
||||
<ListView row="2" class="options" for="item in filterList">
|
||||
<v-template>
|
||||
<Label
|
||||
<RLabel
|
||||
class="listItem"
|
||||
verticalAlignment="center"
|
||||
col="1"
|
||||
|
@ -31,7 +35,12 @@
|
|||
/>
|
||||
</v-template>
|
||||
</ListView>
|
||||
<GridLayout row="3" columns="auto, *, auto, auto" class="actions">
|
||||
<RGridLayout
|
||||
:rtl="RTL"
|
||||
row="3"
|
||||
columns="auto, *, auto, auto"
|
||||
class="actions"
|
||||
>
|
||||
<Button class="text sm" :text="'rest' | L" @tap="resetFilter" />
|
||||
<Button
|
||||
col="2"
|
||||
|
@ -45,7 +54,7 @@
|
|||
:text="'apply' | L"
|
||||
@tap="applyFilter"
|
||||
/>
|
||||
</GridLayout>
|
||||
</RGridLayout>
|
||||
</GridLayout>
|
||||
</Page>
|
||||
</template>
|
||||
|
@ -61,7 +70,7 @@ export default {
|
|||
localCuisine: null,
|
||||
localCategory: null,
|
||||
localTag: null,
|
||||
reset: false,
|
||||
reset: 0,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -70,10 +79,11 @@ export default {
|
|||
"recipes",
|
||||
"cuisines",
|
||||
"categories",
|
||||
"selectedCuisine",
|
||||
"selectedCategory",
|
||||
"selectedTag",
|
||||
"appTheme",
|
||||
"selCuisine",
|
||||
"selCategory",
|
||||
"selTag",
|
||||
"theme",
|
||||
"RTL",
|
||||
]),
|
||||
pathList() {
|
||||
let arr = [
|
||||
|
@ -163,18 +173,12 @@ export default {
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions([
|
||||
"setComponent",
|
||||
"setCuisine",
|
||||
"setCategory",
|
||||
"setTag",
|
||||
"clearFilter",
|
||||
]),
|
||||
onPageLoad(args) {
|
||||
...mapActions(["setCuisine", "setCategory", "setTag", "clearFilter"]),
|
||||
pgLoad(args) {
|
||||
this.transparentPage(args);
|
||||
this.localCuisine = this.selectedCuisine;
|
||||
this.localCategory = this.selectedCategory;
|
||||
this.localTag = this.selectedTag;
|
||||
this.localCuisine = this.selCuisine;
|
||||
this.localCategory = this.selCategory;
|
||||
this.localTag = this.selTag;
|
||||
if (this.localCuisine) this.filterType = "category";
|
||||
if (this.localCategory && this.localTag) this.filterType = "tag";
|
||||
this.scrollToRight();
|
||||
|
@ -198,14 +202,14 @@ export default {
|
|||
setTimeout(
|
||||
() =>
|
||||
this.scrollview.scrollToHorizontalOffset(
|
||||
this.scrollview.scrollableWidth,
|
||||
this.RTL ? 0 : this.scrollview.scrollableWidth,
|
||||
true
|
||||
),
|
||||
10
|
||||
);
|
||||
},
|
||||
setRecipeFilter(item) {
|
||||
this.reset = false;
|
||||
this.reset = 0;
|
||||
switch (this.filterType) {
|
||||
case "cuisine":
|
||||
this.localCuisine = item;
|
||||
|
@ -225,27 +229,26 @@ export default {
|
|||
this.setCuisine(this.localCuisine);
|
||||
this.setCategory(this.localCategory);
|
||||
this.setTag(this.localTag);
|
||||
this.filterFavourites = this.filterTrylater = false;
|
||||
if (this.reset) this.setComponent("EnRecipes");
|
||||
else this.setComponent("Filtered recipes");
|
||||
this.$modal.close();
|
||||
this.filterFavourites = this.filterTrylater = 0;
|
||||
this.$modal.close(this.reset);
|
||||
},
|
||||
resetFilter() {
|
||||
this.filterType = "cuisine";
|
||||
this.localCuisine = this.localCategory = this.localTag = null;
|
||||
this.reset = true;
|
||||
this.reset = 1;
|
||||
},
|
||||
touch({ object, action }, item) {
|
||||
object.className = action.match(/down|move/)
|
||||
? "listItem fade"
|
||||
: "listItem";
|
||||
: "listItem ";
|
||||
if (action == "up") this.setRecipeFilter(item);
|
||||
},
|
||||
touchSelector({ object, action }, type) {
|
||||
let selected = this.filterType == type;
|
||||
let classes = `segment ${this.RTL ? "rtl" : ""} `;
|
||||
object.className = action.match(/down|move/)
|
||||
? `segment ${selected ? "select" : "fade"}`
|
||||
: `segment ${selected && "select"}`;
|
||||
? `${classes}${selected ? "select" : "fade"}`
|
||||
: `${classes}${selected && "select"}`;
|
||||
if (action == "up") this.setFilterType(type);
|
||||
},
|
||||
},
|
||||
|
|
|
@ -2,24 +2,35 @@
|
|||
<Page
|
||||
@loaded="transparentPage"
|
||||
backgroundColor="transparent"
|
||||
:class="appTheme"
|
||||
:class="theme"
|
||||
>
|
||||
<GridLayout rows="auto, auto, auto" class="modal">
|
||||
<Label class="title" :text="title | L" />
|
||||
<RLabel class="title" :text="title | L" />
|
||||
<StackLayout row="1" class="input">
|
||||
<TextView
|
||||
v-if="type == 'view'"
|
||||
autocorrect="true"
|
||||
autocapitalizationType="sentences"
|
||||
class="modalInput"
|
||||
@loaded="focusField"
|
||||
v-model="text"
|
||||
/>
|
||||
<TextField
|
||||
autocapitalizationType="sentences"
|
||||
autocorrect="true"
|
||||
v-else
|
||||
class="modalInput"
|
||||
@loaded="focusField"
|
||||
v-model="text"
|
||||
@returnPress="$modal.close(text)"
|
||||
/>
|
||||
</StackLayout>
|
||||
<GridLayout row="2" columns="*, auto, auto" class="actions">
|
||||
<RGridLayout :rtl="RTL" row="2" columns="*, auto, auto" class="actions">
|
||||
<Button
|
||||
col="1"
|
||||
class="text sm"
|
||||
:text="'cBtn' | L"
|
||||
@tap="$modal.close(false)"
|
||||
@tap="$modal.close(0)"
|
||||
/>
|
||||
<Button
|
||||
col="2"
|
||||
|
@ -27,7 +38,7 @@
|
|||
:text="action | L"
|
||||
@tap="$modal.close(text)"
|
||||
/>
|
||||
</GridLayout>
|
||||
</RGridLayout>
|
||||
</GridLayout>
|
||||
</Page>
|
||||
</template>
|
||||
|
@ -37,20 +48,23 @@ import { Utils } from "@nativescript/core";
|
|||
import { localize } from "@nativescript/localize";
|
||||
import { mapState } from "vuex";
|
||||
export default {
|
||||
props: ["title", "hint", "placeholder", "action"],
|
||||
props: ["title", "type", "hint", "placeholder", "action"],
|
||||
data() {
|
||||
return {
|
||||
text: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(["icon", "appTheme"]),
|
||||
...mapState(["icon", "theme", "RTL"]),
|
||||
},
|
||||
methods: {
|
||||
focusField({ object }) {
|
||||
this.setGravity(object);
|
||||
let a = this.placeholder;
|
||||
typeof a == "number"
|
||||
? (object.keyboardType = "number")
|
||||
: this.type
|
||||
? ""
|
||||
: (object.autocapitalizationType = "words");
|
||||
object.hint = this.hint;
|
||||
object.focus();
|
||||
|
|
|
@ -2,45 +2,43 @@
|
|||
<Page
|
||||
@loaded="transparentPage"
|
||||
backgroundColor="transparent"
|
||||
:class="appTheme"
|
||||
:class="theme"
|
||||
>
|
||||
<GridLayout rows="auto, auto, auto" class="modal">
|
||||
<Label class="title" :text="title | L" />
|
||||
<StackLayout
|
||||
<RLabel class="title" :text="title | L" />
|
||||
<RStackLayout
|
||||
:rtl="RTL"
|
||||
row="1"
|
||||
class="dialogListPicker"
|
||||
orientation="horizontal"
|
||||
horizontalAlignment="center"
|
||||
>
|
||||
<ListPicker
|
||||
@loaded="onLPLoad"
|
||||
ref="hrPicker"
|
||||
:items="hrsList"
|
||||
:selectedIndex="hrIndex"
|
||||
@selectedIndexChange="setHrs"
|
||||
></ListPicker>
|
||||
<ListPicker
|
||||
@loaded="onLPLoad"
|
||||
ref="minPicker"
|
||||
:items="minsList"
|
||||
:selectedIndex="minIndex"
|
||||
@selectedIndexChange="setMins"
|
||||
></ListPicker>
|
||||
</StackLayout>
|
||||
<GridLayout row="2" columns="*, auto, auto" class="actions">
|
||||
</RStackLayout>
|
||||
<RGridLayout :rtl="RTL" row="2" columns="*, auto, auto" class="actions">
|
||||
<Button
|
||||
col="1"
|
||||
class="text sm"
|
||||
:text="'cBtn' | L"
|
||||
@tap="$modal.close(false)"
|
||||
@tap="$modal.close(0)"
|
||||
/>
|
||||
<Button
|
||||
col="2"
|
||||
class="text sm"
|
||||
:text="action | L"
|
||||
:text="'SET' | L"
|
||||
@tap="$modal.close(selectedTime)"
|
||||
/>
|
||||
</GridLayout>
|
||||
</RGridLayout>
|
||||
</GridLayout>
|
||||
</Page>
|
||||
</template>
|
||||
|
@ -49,7 +47,7 @@
|
|||
import { mapState } from "vuex";
|
||||
import { localize } from "@nativescript/localize";
|
||||
export default {
|
||||
props: ["title", "selectedHr", "selectedMin", "action"],
|
||||
props: ["title", "selectedHr", "selectedMin"],
|
||||
data() {
|
||||
return {
|
||||
hrs: [],
|
||||
|
@ -59,7 +57,7 @@ export default {
|
|||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(["icon", "appTheme"]),
|
||||
...mapState(["icon", "theme", "RTL"]),
|
||||
hrsList() {
|
||||
let h = [...Array(24).keys()];
|
||||
this.hrs = h;
|
||||
|
|
|
@ -2,20 +2,25 @@
|
|||
<Page
|
||||
@loaded="transparentPage"
|
||||
backgroundColor="transparent"
|
||||
:class="appTheme"
|
||||
:class="theme"
|
||||
>
|
||||
<GridLayout rows="auto, auto, auto" class="modal">
|
||||
<Label class="title" :text="title | L" />
|
||||
<RLabel class="title" :text="title | L" />
|
||||
<StackLayout row="1">
|
||||
<StackLayout class="input">
|
||||
<TextField
|
||||
@loaded="setGravity"
|
||||
class="modalInput"
|
||||
v-model="setLabel"
|
||||
:hint="label"
|
||||
autocapitalizationType="words"
|
||||
autocorrect="true"
|
||||
/></StackLayout>
|
||||
<!-- @loaded="focusField" -->
|
||||
<StackLayout orientation="horizontal" horizontalAlignment="center">
|
||||
<RStackLayout
|
||||
:rtl="RTL"
|
||||
orientation="horizontal"
|
||||
horizontalAlignment="center"
|
||||
>
|
||||
<ListPicker
|
||||
@loaded="onLPLoad"
|
||||
:items="hrsList"
|
||||
|
@ -31,10 +36,15 @@
|
|||
:items="secsList"
|
||||
@selectedIndexChange="setSec"
|
||||
></ListPicker>
|
||||
</StackLayout>
|
||||
</RStackLayout>
|
||||
</StackLayout>
|
||||
|
||||
<GridLayout row="2" columns="auto, *, auto, auto" class="actions">
|
||||
<RGridLayout
|
||||
:rtl="RTL"
|
||||
row="2"
|
||||
columns="auto, *, auto, auto"
|
||||
class="actions r"
|
||||
>
|
||||
<Button
|
||||
v-if="showPreset"
|
||||
class="text sm"
|
||||
|
@ -45,10 +55,10 @@
|
|||
col="2"
|
||||
class="text sm"
|
||||
:text="'cBtn' | L"
|
||||
@tap="$modal.close(false)"
|
||||
@tap="$modal.close(0)"
|
||||
/>
|
||||
<Button col="3" class="text sm" :text="action | L" @tap="sendRespose" />
|
||||
</GridLayout>
|
||||
</RGridLayout>
|
||||
</GridLayout>
|
||||
</Page>
|
||||
</template>
|
||||
|
@ -71,7 +81,7 @@ export default {
|
|||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(["icon", "appTheme"]),
|
||||
...mapState(["icon", "theme", "RTL"]),
|
||||
hrsList() {
|
||||
let h = [...Array(24).keys()];
|
||||
this.hrs = h;
|
||||
|
|
114
app/components/modals/TimerReminder.vue
Normal file
|
@ -0,0 +1,114 @@
|
|||
<template>
|
||||
<Page @loaded="pgLoad" :class="theme" backgroundColor="#ff5200">
|
||||
<GridLayout rows="*, *">
|
||||
<Button
|
||||
class="ico fab"
|
||||
fontSize="128"
|
||||
:width="screenWidth"
|
||||
:height="screenWidth"
|
||||
:text="icon.timer"
|
||||
/>
|
||||
<GridLayout row="1" rows="*, auto" columns="*, auto, *">
|
||||
<ScrollView :class="theme" rowSpan="2" colSpan="3">
|
||||
<StackLayout paddingTop="8">
|
||||
<Timer
|
||||
v-for="timer in timers"
|
||||
:key="timer.id"
|
||||
:timer="timer"
|
||||
:formattedTime="formattedTime"
|
||||
:removeTimer="removeTimer"
|
||||
:togglePause="togglePause"
|
||||
:timerAlert="timerAlert"
|
||||
:showToast="showToast"
|
||||
/>
|
||||
<StackLayout class="listSpace"> </StackLayout>
|
||||
</StackLayout>
|
||||
</ScrollView>
|
||||
<GridLayout col="1" row="1" class="appbar">
|
||||
<Button
|
||||
class="ico fab"
|
||||
margin="0"
|
||||
:text="icon.x"
|
||||
@tap="removeTimers"
|
||||
col="1"
|
||||
/>
|
||||
</GridLayout>
|
||||
</GridLayout>
|
||||
</GridLayout>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Application, Screen, Device, Color, Utils } from "@nativescript/core";
|
||||
import Timer from "../sub/Timer.vue";
|
||||
import * as utils from "~/shared/utils";
|
||||
import { mapState, mapActions } from "vuex";
|
||||
const windowMgr = android.view.WindowManager;
|
||||
const View = android.view.View as any;
|
||||
const ViewGroup = android.view.ViewGroup;
|
||||
export default {
|
||||
components: { Timer },
|
||||
props: [
|
||||
"formattedTime",
|
||||
"removeTimer",
|
||||
"togglePause",
|
||||
"timerAlert",
|
||||
"showToast",
|
||||
],
|
||||
computed: {
|
||||
...mapState(["icon", "theme", "activeTimers"]),
|
||||
screenWidth() {
|
||||
return Screen.mainScreen.widthDIPs;
|
||||
},
|
||||
timers() {
|
||||
let timers = this.activeTimers.filter((e) => e.done);
|
||||
if (!timers.length) {
|
||||
this.$modal.close(1);
|
||||
this.isScreenLocked && this.turnOffScreen();
|
||||
}
|
||||
return timers;
|
||||
},
|
||||
sdkv() {
|
||||
return parseInt(Device.sdkVersion);
|
||||
},
|
||||
isScreenLocked() {
|
||||
const keyguardMgr = Utils.ad
|
||||
.getApplicationContext()
|
||||
.getSystemService(android.content.Context.KEYGUARD_SERVICE);
|
||||
return this.sdkv > 21
|
||||
? keyguardMgr.isDeviceLocked()
|
||||
: keyguardMgr.isKeyguardLocked();
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions(["clearTimerInterval"]),
|
||||
pgLoad({ object }) {
|
||||
let dialog = object._dialogFragment.getDialog();
|
||||
let dialogWindow = dialog.getWindow();
|
||||
let decorView = dialogWindow.getDecorView();
|
||||
dialog.setCancelable(false);
|
||||
if (this.isScreenLocked) {
|
||||
const flags =
|
||||
windowMgr.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
|
||||
windowMgr.LayoutParams.FLAG_TURN_SCREEN_ON |
|
||||
windowMgr.LayoutParams.FLAG_KEEP_SCREEN_ON;
|
||||
dialogWindow.addFlags(flags);
|
||||
}
|
||||
utils.setBarColors(dialogWindow, decorView, this.theme);
|
||||
dialogWindow.setStatusBarColor(new Color("#ff5200").android);
|
||||
},
|
||||
removeTimers() {
|
||||
this.timers.forEach((timer) => this.removeTimer(timer.id, 1));
|
||||
this.isScreenLocked && this.turnOffScreen();
|
||||
},
|
||||
turnOffScreen() {
|
||||
const window = Application.android.startActivity.getWindow();
|
||||
const flags =
|
||||
windowMgr.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
|
||||
windowMgr.LayoutParams.FLAG_TURN_SCREEN_ON |
|
||||
windowMgr.LayoutParams.FLAG_KEEP_SCREEN_ON;
|
||||
window.clearFlags(flags);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
|
@ -1,12 +1,7 @@
|
|||
<template>
|
||||
<Page @loaded="onPageLoad" actionBarHidden="true">
|
||||
<GridLayout rows="*, auto" columns="auto, *">
|
||||
<ListView
|
||||
rowSpan="2"
|
||||
colSpan="2"
|
||||
class="options-list"
|
||||
for="item in items"
|
||||
>
|
||||
<Page @loaded="pgLoad" actionBarHidden="true">
|
||||
<RGridLayout :rtl="RTL" rows="*, auto" columns="auto, *">
|
||||
<ListView rowSpan="2" colSpan="2" class="options" for="item in items">
|
||||
<v-template if="$index == 0">
|
||||
<Label class="pageTitle" :text="'About' | L" />
|
||||
</v-template>
|
||||
|
@ -23,20 +18,26 @@
|
|||
<StackLayout class="listSpace"> </StackLayout>
|
||||
</v-template>
|
||||
<v-template>
|
||||
<GridLayout
|
||||
<RGridLayout
|
||||
:rtl="RTL"
|
||||
columns="auto, *"
|
||||
class="option"
|
||||
@touch="touch($event, item.url)"
|
||||
>
|
||||
<Label class="ico" :text="icon[item.icon]" />
|
||||
<Label col="1" :text="item.title | L" />
|
||||
</GridLayout>
|
||||
<Label
|
||||
class="ico"
|
||||
:class="{ rtl: /help|don/.test(item.icon) }"
|
||||
:text="icon[item.icon]"
|
||||
/>
|
||||
|
||||
<Label col="1" class="info" :text="item.title | L" />
|
||||
</RGridLayout>
|
||||
</v-template>
|
||||
</ListView>
|
||||
<GridLayout row="1" class="appbar" rows="*" columns="auto, *">
|
||||
<GridLayout row="1" class="appbar rtl" rows="*" columns="auto, *">
|
||||
<Button class="ico" :text="icon.back" @tap="$navigateBack()" />
|
||||
</GridLayout>
|
||||
</GridLayout>
|
||||
</RGridLayout>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
|
@ -46,7 +47,7 @@ import { mapState } from "vuex";
|
|||
|
||||
export default {
|
||||
computed: {
|
||||
...mapState(["icon"]),
|
||||
...mapState(["icon", "RTL"]),
|
||||
items() {
|
||||
return [
|
||||
{},
|
||||
|
@ -69,8 +70,7 @@ export default {
|
|||
{
|
||||
icon: "priv",
|
||||
title: "priv",
|
||||
url:
|
||||
"https://github.com/vishnuraghavb/EnRecipes/blob/main/PRIVACY.md",
|
||||
url: "https://github.com/vishnuraghavb/EnRecipes/blob/main/PRIVACY.md",
|
||||
},
|
||||
{
|
||||
icon: "don",
|
||||
|
@ -95,7 +95,7 @@ export default {
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
onPageLoad({ object }) {
|
||||
pgLoad({ object }) {
|
||||
object.bindingContext = new Observable();
|
||||
},
|
||||
// HELPERS
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
<template>
|
||||
<Page @loaded="onPageLoad" actionBarHidden="true">
|
||||
<GridLayout rows="*, auto" columns="auto, *">
|
||||
<Page @loaded="pgLoad" actionBarHidden="true">
|
||||
<RGridLayout :rtl="RTL" rows="*, auto" columns="auto, *">
|
||||
<OptionsList title="Settings" :items="items" :action="navigateTo" />
|
||||
<GridLayout row="1" class="appbar" rows="*" columns="auto, *">
|
||||
<GridLayout row="1" class="appbar rtl" rows="*" columns="auto, *">
|
||||
<Button class="ico" :text="icon.back" @tap="$navigateBack()" />
|
||||
</GridLayout>
|
||||
</GridLayout>
|
||||
</RGridLayout>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Observable } from "@nativescript/core";
|
||||
import { mapState, mapActions } from "vuex";
|
||||
import { mapState } from "vuex";
|
||||
import Interface from "./Interface.vue";
|
||||
import Options from "./Options.vue";
|
||||
import Database from "./Database.vue";
|
||||
|
@ -27,30 +27,35 @@ export default {
|
|||
{
|
||||
type: "list",
|
||||
icon: "interface",
|
||||
rtl: 0,
|
||||
title: "intf",
|
||||
data: Interface,
|
||||
},
|
||||
{
|
||||
type: "list",
|
||||
icon: "opts",
|
||||
rtl: 1,
|
||||
title: "opts",
|
||||
data: Options,
|
||||
},
|
||||
{
|
||||
type: "list",
|
||||
icon: "db",
|
||||
rtl: 0,
|
||||
title: "db",
|
||||
data: Database,
|
||||
},
|
||||
{
|
||||
type: "list",
|
||||
icon: "reset",
|
||||
rtl: 1,
|
||||
title: "rest",
|
||||
data: Reset,
|
||||
},
|
||||
{
|
||||
type: "list",
|
||||
icon: "info",
|
||||
rtl: 0,
|
||||
title: "About",
|
||||
data: About,
|
||||
},
|
||||
|
@ -59,22 +64,16 @@ export default {
|
|||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(["icon"]),
|
||||
...mapState(["icon", "RTL"]),
|
||||
},
|
||||
methods: {
|
||||
...mapActions(["setComponent"]),
|
||||
onPageLoad({ object }) {
|
||||
pgLoad({ object }) {
|
||||
object.bindingContext = new Observable();
|
||||
this.setComponent("Settings");
|
||||
},
|
||||
// HELPERS
|
||||
navigateTo(view) {
|
||||
this.$navigateTo(view, {
|
||||
transition: {
|
||||
name: "slide",
|
||||
duration: 200,
|
||||
curve: "easeOut",
|
||||
},
|
||||
animated: false,
|
||||
});
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1,16 +1,22 @@
|
|||
<template>
|
||||
<Page @loaded="onPageLoad" actionBarHidden="true">
|
||||
<GridLayout rows="*, auto" columns="auto, *">
|
||||
<Page @loaded="pgLoad" actionBarHidden="true">
|
||||
<RGridLayout :rtl="RTL" rows="*, auto" columns="auto, *">
|
||||
<OptionsList title="Settings" :items="items" />
|
||||
<GridLayout row="1" class="appbar" rows="*" columns="auto, *">
|
||||
<GridLayout row="1" class="appbar rtl" rows="*" columns="auto, *">
|
||||
<Button class="ico" :text="icon.back" @tap="$navigateBack()" />
|
||||
</GridLayout>
|
||||
</GridLayout>
|
||||
</RGridLayout>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Observable, Device, Application, Utils } from "@nativescript/core";
|
||||
import {
|
||||
Observable,
|
||||
Device,
|
||||
Application,
|
||||
ApplicationSettings,
|
||||
Utils,
|
||||
} from "@nativescript/core";
|
||||
import { mapState, mapActions } from "vuex";
|
||||
import { localize } from "@nativescript/localize";
|
||||
import OptionsList from "../sub/OptionsList";
|
||||
|
@ -20,12 +26,13 @@ import * as utils from "~/shared/utils";
|
|||
export default {
|
||||
components: { OptionsList },
|
||||
computed: {
|
||||
...mapState(["icon", "timerDelay", "timerSound", "timerVibrate"]),
|
||||
...mapState(["icon", "timerDelay", "timerSound", "timerVibrate", "RTL"]),
|
||||
items() {
|
||||
let options = [
|
||||
{
|
||||
type: "list",
|
||||
icon: "sound",
|
||||
rtl: 0,
|
||||
title: "tmrSnd",
|
||||
subTitle: this.timerSound.title,
|
||||
action: this.showSoundsList,
|
||||
|
@ -33,8 +40,9 @@ export default {
|
|||
{
|
||||
type: "switch",
|
||||
icon: "vibrate",
|
||||
rtl: 0,
|
||||
title: "tmrvbrt",
|
||||
checked: this.timerVibrate,
|
||||
checked: !!this.timerVibrate,
|
||||
action: this.toggleTimerVibrate,
|
||||
},
|
||||
];
|
||||
|
@ -42,6 +50,7 @@ export default {
|
|||
{
|
||||
type: "list",
|
||||
icon: "sound",
|
||||
rtl: 0,
|
||||
title: "notifSetg",
|
||||
subTitle: null,
|
||||
action: this.openNotificationChannelSettings,
|
||||
|
@ -53,39 +62,50 @@ export default {
|
|||
{
|
||||
type: "list",
|
||||
icon: "delay",
|
||||
rtl: 0,
|
||||
title: "dlyDur",
|
||||
subTitle: this.timerDelay,
|
||||
subTitle:
|
||||
this.delayList[
|
||||
this.delayList.findIndex((e) => e.n == this.timerDelay)
|
||||
].l,
|
||||
action: this.showDelayList,
|
||||
},
|
||||
...list,
|
||||
{},
|
||||
];
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions([
|
||||
"setTimerDelay",
|
||||
"setTimerSound",
|
||||
"setTimerVibrate",
|
||||
"setComponent",
|
||||
]),
|
||||
onPageLoad({ object }) {
|
||||
object.bindingContext = new Observable();
|
||||
this.setComponent("CTSettings");
|
||||
},
|
||||
showDelayList() {
|
||||
let list = [
|
||||
delayList() {
|
||||
return [
|
||||
...Array.from(Array(4), (_, x) => x + 1),
|
||||
...Array.from(Array(6), (_, x) => (x + 1) * 5),
|
||||
].map(
|
||||
(e, i) => `${e} ${i == 0 ? localize("minute") : localize("minutes")}`
|
||||
);
|
||||
].map((e) => {
|
||||
return {
|
||||
l: `${this.getLocaleN(e)} ${localize(e > 1 ? "minutes" : "minute")}`,
|
||||
n: e,
|
||||
};
|
||||
});
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions(["setTimerDelay", "setTimerSound", "setTimerVibrate"]),
|
||||
pgLoad({ object }) {
|
||||
object.bindingContext = new Observable();
|
||||
ApplicationSettings.setNumber("isTimer", 2);
|
||||
},
|
||||
showDelayList() {
|
||||
this.$showModal(Action, {
|
||||
props: {
|
||||
title: "dlyDur",
|
||||
list,
|
||||
list: this.delayList.map((e) => e.l),
|
||||
selected: this.delayList.findIndex((e) => e.n == this.timerDelay),
|
||||
},
|
||||
}).then((dur) => dur && this.setTimerDelay(dur));
|
||||
}).then(
|
||||
(res) =>
|
||||
res &&
|
||||
this.setTimerDelay(
|
||||
this.delayList[this.delayList.findIndex((e) => e.l == res)].n
|
||||
)
|
||||
);
|
||||
},
|
||||
showSoundsList() {
|
||||
let getTones = utils.getTones();
|
||||
|
@ -102,7 +122,7 @@ export default {
|
|||
);
|
||||
},
|
||||
toggleTimerVibrate() {
|
||||
this.setTimerVibrate(!this.timerVibrate);
|
||||
this.setTimerVibrate(!this.timerVibrate | 0);
|
||||
},
|
||||
openNotificationChannelSettings() {
|
||||
const ctx = Application.android.context;
|
||||
|
|
|
@ -1,28 +1,30 @@
|
|||
<template>
|
||||
<Page @loaded="onPageLoad" actionBarHidden="true">
|
||||
<GridLayout rows="*, auto" columns="auto, *">
|
||||
<Page @loaded="pgLoad" actionBarHidden="true">
|
||||
<RGridLayout :rtl="RTL" rows="*, auto" columns="auto, *">
|
||||
<OptionsList title="db" :items="items" />
|
||||
<GridLayout
|
||||
v-show="!toast && !progress"
|
||||
:hidden="toast || progress"
|
||||
@loaded="abLoad"
|
||||
row="1"
|
||||
class="appbar"
|
||||
class="appbar rtl"
|
||||
rows="*"
|
||||
columns="auto, *"
|
||||
>
|
||||
<Button class="ico" :text="icon.back" @tap="$navigateBack()" />
|
||||
</GridLayout>
|
||||
<Toast :toast="toast" :action="hideToast" />
|
||||
<GridLayout
|
||||
<Toast :onload="tbLoad" :toast="toast" :action="hideBar" />
|
||||
<RGridLayout
|
||||
:rtl="RTL"
|
||||
v-show="progress"
|
||||
row="1"
|
||||
colSpan="2"
|
||||
class="appbar snackBar"
|
||||
class="appbar snackBar rtl"
|
||||
columns="auto, *"
|
||||
>
|
||||
<ActivityIndicator :busy="progress ? true : false" />
|
||||
<Label col="1" class="title" :text="progress" textWrap="true" />
|
||||
</GridLayout>
|
||||
</GridLayout>
|
||||
<ActivityIndicator :busy="!!progress" />
|
||||
<RLabel col="1" class="title" :text="progress" />
|
||||
</RGridLayout>
|
||||
</RGridLayout>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
|
@ -50,9 +52,11 @@ export default {
|
|||
components: { OptionsList, Toast },
|
||||
data() {
|
||||
return {
|
||||
backupFolder: null,
|
||||
progress: null,
|
||||
toast: null,
|
||||
backupFolder: 0,
|
||||
progress: 0,
|
||||
toast: 0,
|
||||
appbar: 0,
|
||||
toastbar: 0,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -65,6 +69,7 @@ export default {
|
|||
"units",
|
||||
"mealPlans",
|
||||
"importSummary",
|
||||
"RTL",
|
||||
]),
|
||||
items() {
|
||||
return [
|
||||
|
@ -101,13 +106,15 @@ export default {
|
|||
"importRecipesFromDB",
|
||||
"importMealPlansFromJSON",
|
||||
"importMealPlansFromDB",
|
||||
"importTimerPresets",
|
||||
"unlinkBrokenImages",
|
||||
"clearImportSummary",
|
||||
]),
|
||||
onPageLoad({ object }) {
|
||||
pgLoad({ object }) {
|
||||
object.bindingContext = new Observable();
|
||||
const ContentResolver = Application.android.nativeApp.getContentResolver();
|
||||
this.backupFolder = ApplicationSettings.getString("backupFolder");
|
||||
const ContentResolver =
|
||||
Application.android.nativeApp.getContentResolver();
|
||||
this.backupFolder = ApplicationSettings.getString("backupFolder", null);
|
||||
if (
|
||||
!this.backupFolder ||
|
||||
ContentResolver.getPersistedUriPermissions().isEmpty()
|
||||
|
@ -115,22 +122,33 @@ export default {
|
|||
this.backupFolder = null;
|
||||
}
|
||||
},
|
||||
// BACKUP FOLDER PICKER
|
||||
abLoad({ object }) {
|
||||
this.appbar = object;
|
||||
},
|
||||
tbLoad({ object }) {
|
||||
this.toastbar = object;
|
||||
},
|
||||
|
||||
// BackupFolderPicker
|
||||
setBackupFolder(startExport) {
|
||||
const ContentResolver = Application.android.nativeApp.getContentResolver();
|
||||
const ContentResolver =
|
||||
Application.android.nativeApp.getContentResolver();
|
||||
const FLAGS =
|
||||
android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION |
|
||||
android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
|
||||
utils.getBackupFolder().then((uri) => {
|
||||
console.log(uri.toString());
|
||||
if (uri != null) {
|
||||
if (this.backupFolder)
|
||||
// ReleaseExistingPermissions
|
||||
|
||||
if (this.backupFolder && this.backupFolder != uri.toString())
|
||||
ContentResolver.releasePersistableUriPermission(
|
||||
new android.net.Uri.parse(this.backupFolder),
|
||||
FLAGS
|
||||
);
|
||||
this.backupFolder = uri.toString();
|
||||
ApplicationSettings.setString("backupFolder", this.backupFolder);
|
||||
// PERSIST PERMISSIONS
|
||||
// PersistPermissions
|
||||
ContentResolver.takePersistableUriPermission(uri, FLAGS);
|
||||
if (startExport && this.backupFolder) {
|
||||
this.exportBackup();
|
||||
|
@ -141,18 +159,15 @@ export default {
|
|||
|
||||
// EXPORT HANDLERS
|
||||
exportCheck() {
|
||||
const ContentResolver = Application.android.nativeApp.getContentResolver();
|
||||
if (!this.recipes.length) {
|
||||
this.toast = localize("aFBu");
|
||||
utils.timer(5, (val) => {
|
||||
if (!val) this.toast = val;
|
||||
});
|
||||
} else {
|
||||
const ContentResolver =
|
||||
Application.android.nativeApp.getContentResolver();
|
||||
if (!this.recipes.length) this.showToast(localize("aFBu"));
|
||||
else {
|
||||
if (
|
||||
!this.backupFolder ||
|
||||
ContentResolver.getPersistedUriPermissions().isEmpty()
|
||||
) {
|
||||
this.setBackupFolder(true);
|
||||
this.setBackupFolder(1);
|
||||
} else this.exportBackup();
|
||||
}
|
||||
},
|
||||
|
@ -182,7 +197,7 @@ export default {
|
|||
console.log("Backup error: ", err);
|
||||
this.progress = null;
|
||||
this.releaseBackEvent();
|
||||
this.setBackupFolder(true);
|
||||
this.setBackupFolder(1);
|
||||
});
|
||||
},
|
||||
showExportSummary(filename) {
|
||||
|
@ -248,6 +263,8 @@ export default {
|
|||
importImages();
|
||||
} else if (File.exists(recipes)) {
|
||||
// IMPORT FROM JSON FILES
|
||||
console.log("import from json");
|
||||
|
||||
this.isFileDataValid([
|
||||
{
|
||||
path: recipes,
|
||||
|
@ -285,9 +302,10 @@ export default {
|
|||
} else this.failedImport(localize("buInc"));
|
||||
},
|
||||
isFileDataValid(file) {
|
||||
console.log("isFileDataValid");
|
||||
const files = file.filter((e) => File.exists(e.path));
|
||||
if (files.length) {
|
||||
let isValid = files.map(() => false);
|
||||
let isValid = files.map(() => 0);
|
||||
files.forEach((file, i) => {
|
||||
File.fromPath(file.path)
|
||||
.readText()
|
||||
|
@ -299,7 +317,7 @@ export default {
|
|||
);
|
||||
return 0;
|
||||
}
|
||||
if (isValid.every((e) => e === true)) {
|
||||
if (isValid.every((e) => e === 1)) {
|
||||
files.forEach((file) => {
|
||||
File.fromPath(file.path)
|
||||
.readText()
|
||||
|
@ -328,9 +346,9 @@ export default {
|
|||
try {
|
||||
JSON.parse(data) && Array.isArray(JSON.parse(data));
|
||||
} catch (e) {
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
return true;
|
||||
return 1;
|
||||
},
|
||||
extractData(recipesDB) {
|
||||
const db = openOrCreate(recipesDB);
|
||||
|
@ -356,8 +374,14 @@ export default {
|
|||
db.select(`SELECT * FROM mealPlans`).then((res) =>
|
||||
this.importMealPlansFromDB(res)
|
||||
);
|
||||
|
||||
// Import timerPresets
|
||||
db.select(`SELECT * FROM timerPresets`).then((res) =>
|
||||
this.importTimerPresets(res)
|
||||
);
|
||||
},
|
||||
importData(data, db) {
|
||||
console.log("importing");
|
||||
switch (db) {
|
||||
case "recipes":
|
||||
this.importRecipesFromJSON(data);
|
||||
|
@ -405,7 +429,6 @@ export default {
|
|||
File.fromPath(entity._path).remove();
|
||||
});
|
||||
});
|
||||
|
||||
this.showImportSummary();
|
||||
this.unlinkBrokenImages();
|
||||
}
|
||||
|
@ -447,9 +470,19 @@ export default {
|
|||
args.cancel = true;
|
||||
},
|
||||
|
||||
// HELPERS
|
||||
hideToast() {
|
||||
this.toast = null;
|
||||
// TOAST
|
||||
showToast(data) {
|
||||
this.animateBar(this.appbar, 0).then(() => {
|
||||
this.toast = data;
|
||||
this.animateBar(this.toastbar, 1);
|
||||
utils.timer(5, (val) => !val && this.hideBar());
|
||||
});
|
||||
},
|
||||
hideBar() {
|
||||
this.animateBar(this.toastbar, 0).then(() => {
|
||||
this.toast = null;
|
||||
this.animateBar(this.appbar, 1);
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,14 +1,8 @@
|
|||
<template>
|
||||
<Page @loaded="pgLoad" actionBarHidden="true">
|
||||
<RGridLayout :isRtl="RTL" rows="*, auto" columns="auto, *">
|
||||
<RGridLayout :rtl="RTL" rows="*, auto" columns="auto, *">
|
||||
<OptionsList title="intf" :items="items" />
|
||||
<GridLayout
|
||||
:isRtl="RTL"
|
||||
row="1"
|
||||
class="appbar"
|
||||
rows="*"
|
||||
columns="auto, *"
|
||||
>
|
||||
<GridLayout row="1" class="appbar rtl" rows="*" columns="auto, *">
|
||||
<Button class="ico" :text="icon.back" @tap="$navigateBack()" />
|
||||
</GridLayout>
|
||||
</RGridLayout>
|
||||
|
@ -16,18 +10,12 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
ApplicationSettings,
|
||||
Observable,
|
||||
Device,
|
||||
Frame,
|
||||
} from "@nativescript/core";
|
||||
import { localize } from "@nativescript/localize";
|
||||
import { ApplicationSettings, Observable, Frame } from "@nativescript/core";
|
||||
import Action from "../modals/Action";
|
||||
import Confirm from "../modals/Confirm";
|
||||
import OptionsList from "../sub/OptionsList";
|
||||
import { mapState, mapActions } from "vuex";
|
||||
import * as utils from "~/shared/utils";
|
||||
import { localize } from "@nativescript/localize";
|
||||
|
||||
export default {
|
||||
components: { OptionsList },
|
||||
|
@ -37,29 +25,34 @@ export default {
|
|||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(["icon", "language", "appTheme", "layout", "RTL"]),
|
||||
...mapState(["icon", "language", "theme", "layout", "RTL"]),
|
||||
items() {
|
||||
return [
|
||||
{},
|
||||
{
|
||||
type: "list",
|
||||
icon: "lang",
|
||||
rtl: 0,
|
||||
title: "lang",
|
||||
subTitle: this.applang,
|
||||
subTitle: localize(this.applang),
|
||||
action: this.setAppLang,
|
||||
},
|
||||
{
|
||||
type: "list",
|
||||
icon: "theme",
|
||||
rtl: 0,
|
||||
title: "Theme",
|
||||
subTitle: ApplicationSettings.getString("appTheme", "sysDef"),
|
||||
subTitle: localize(
|
||||
ApplicationSettings.getString("theme", "sysDef")
|
||||
),
|
||||
action: this.selectThemes,
|
||||
},
|
||||
{
|
||||
type: "list",
|
||||
icon: "layout",
|
||||
rtl: 1,
|
||||
title: "listVM",
|
||||
subTitle: this.layout,
|
||||
subTitle: localize(this.layout),
|
||||
action: this.setLayoutMode,
|
||||
},
|
||||
{},
|
||||
|
@ -93,6 +86,7 @@ export default {
|
|||
ApplicationSettings.setString("appLocale", locale);
|
||||
utils.updateLocale();
|
||||
this.setRTL();
|
||||
Frame.reloadPage();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -107,9 +101,9 @@ export default {
|
|||
}).then((action) => {
|
||||
if (
|
||||
action &&
|
||||
(ApplicationSettings.getString("appTheme") != this.appTheme
|
||||
(ApplicationSettings.getString("theme") != this.theme
|
||||
? 1
|
||||
: this.appTheme != action)
|
||||
: this.theme != action)
|
||||
) {
|
||||
this.setTheme(action);
|
||||
Frame.reloadPage();
|
||||
|
|
|
@ -1,44 +1,80 @@
|
|||
<template>
|
||||
<Page @loaded="onPageLoad" actionBarHidden="true">
|
||||
<GridLayout rows="*, auto" columns="auto, *">
|
||||
<Page @loaded="pgLoad" actionBarHidden="true">
|
||||
<RGridLayout :rtl="RTL" rows="*, auto" columns="auto, *">
|
||||
<OptionsList title="Settings" :items="items" />
|
||||
<GridLayout row="1" class="appbar" rows="*" columns="auto, *">
|
||||
<GridLayout row="1" class="appbar rtl" rows="*" columns="auto, *">
|
||||
<Button class="ico" :text="icon.back" @tap="$navigateBack()" />
|
||||
</GridLayout>
|
||||
</GridLayout>
|
||||
</RGridLayout>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Observable } from "@nativescript/core";
|
||||
import { mapState, mapActions } from "vuex";
|
||||
import Action from "../modals/Action";
|
||||
import OptionsList from "../sub/OptionsList";
|
||||
import { localize } from "@nativescript/localize";
|
||||
|
||||
export default {
|
||||
components: { OptionsList },
|
||||
computed: {
|
||||
...mapState(["icon", "mondayFirst"]),
|
||||
...mapState(["icon", "mondayFirst", "RTL", "plannerView", "planDeletion"]),
|
||||
items() {
|
||||
return [
|
||||
{},
|
||||
{
|
||||
type: "list",
|
||||
icon: "calv",
|
||||
title: "calVM",
|
||||
subTitle: localize(this.plannerView),
|
||||
action: this.selectPlannerView,
|
||||
},
|
||||
{
|
||||
type: "switch",
|
||||
icon: "week",
|
||||
title: "swm",
|
||||
checked: this.mondayFirst,
|
||||
checked: !!this.mondayFirst,
|
||||
action: this.toggleFirstDay,
|
||||
},
|
||||
{
|
||||
type: "list",
|
||||
icon: "mpd",
|
||||
title: "admp",
|
||||
subTitle: localize(this.planDeletion),
|
||||
action: this.selectDeletionTime,
|
||||
},
|
||||
{},
|
||||
];
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions(["setFirstDay"]),
|
||||
onPageLoad({ object }) {
|
||||
...mapActions(["setFirstDay", "setPlannerView", "setPlanDeletion"]),
|
||||
pgLoad({ object }) {
|
||||
object.bindingContext = new Observable();
|
||||
},
|
||||
toggleFirstDay() {
|
||||
this.setFirstDay(!this.mondayFirst);
|
||||
this.setFirstDay(!this.mondayFirst | 0);
|
||||
},
|
||||
selectPlannerView() {
|
||||
this.$showModal(Action, {
|
||||
props: {
|
||||
title: "calVM",
|
||||
list: ["mnth", "wk", "d"],
|
||||
},
|
||||
}).then((res) => {
|
||||
if (res && this.plannerView != res) this.setPlannerView(res);
|
||||
});
|
||||
},
|
||||
selectDeletionTime() {
|
||||
this.$showModal(Action, {
|
||||
props: {
|
||||
title: "admp",
|
||||
list: ["otay", "otam", "otaw", "nvr"],
|
||||
},
|
||||
}).then((res) => {
|
||||
if (res && this.planDeletion != res) this.setPlanDeletion(res);
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
<template>
|
||||
<Page @loaded="onPageLoad" actionBarHidden="true">
|
||||
<GridLayout rows="*, auto" columns="auto, *">
|
||||
<Page @loaded="pgLoad" actionBarHidden="true">
|
||||
<RGridLayout :rtl="RTL" rows="*, auto" columns="auto, *">
|
||||
<OptionsList title="opts" :items="items" />
|
||||
<GridLayout
|
||||
v-show="!toast"
|
||||
:hidden="toast"
|
||||
@loaded="abLoad"
|
||||
row="1"
|
||||
class="appbar"
|
||||
class="appbar rtl"
|
||||
rows="*"
|
||||
columns="auto, *"
|
||||
>
|
||||
<Button class="ico" :text="icon.back" @tap="$navigateBack()" />
|
||||
</GridLayout>
|
||||
<Toast :toast="toast" :action="(toast = null)" />
|
||||
</GridLayout>
|
||||
<Toast :onload="tbLoad" :toast="toast" :action="hideBar" />
|
||||
</RGridLayout>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
|
@ -28,11 +29,13 @@ export default {
|
|||
components: { OptionsList, Toast },
|
||||
data() {
|
||||
return {
|
||||
appbar: null,
|
||||
toastbar: null,
|
||||
toast: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(["icon", "shakeEnabled"]),
|
||||
...mapState(["icon", "shake", "RTL"]),
|
||||
items() {
|
||||
return [
|
||||
{},
|
||||
|
@ -40,8 +43,8 @@ export default {
|
|||
type: "switch",
|
||||
icon: "shuf",
|
||||
title: "sVw",
|
||||
subTitle: "sVwInfo",
|
||||
checked: this.shakeEnabled,
|
||||
subTitle: localize("sVwInfo"),
|
||||
checked: !!this.shake,
|
||||
action: this.toggleShake,
|
||||
},
|
||||
{},
|
||||
|
@ -50,19 +53,35 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
...mapActions(["setShake"]),
|
||||
onPageLoad({ object }) {
|
||||
pgLoad({ object }) {
|
||||
object.bindingContext = new Observable();
|
||||
},
|
||||
abLoad({ object }) {
|
||||
this.appbar = object;
|
||||
},
|
||||
tbLoad({ object }) {
|
||||
this.toastbar = object;
|
||||
},
|
||||
|
||||
// SHAKE VIEW RANDOM RECIPE
|
||||
toggleShake() {
|
||||
let checked = this.shakeEnabled;
|
||||
if (checked && !utils.hasAccelerometer()) {
|
||||
this.toast = localize("noAccSensor");
|
||||
utils.timer(5, (val) => {
|
||||
if (!val) this.toast = val;
|
||||
});
|
||||
} else this.setShake(!checked);
|
||||
let checked = this.shake;
|
||||
if (checked && !utils.hasAccelerometer())
|
||||
this.showToast(localize("noAccSensor"));
|
||||
else this.setShake(!checked | 0);
|
||||
},
|
||||
showToast(data) {
|
||||
this.animateBar(this.appbar, 0).then(() => {
|
||||
this.toast = data;
|
||||
this.animateBar(this.toastbar, 1);
|
||||
utils.timer(5, (val) => !val && this.hideBar());
|
||||
});
|
||||
},
|
||||
hideBar() {
|
||||
this.animateBar(this.toastbar, 0).then(() => {
|
||||
this.toast = null;
|
||||
this.animateBar(this.appbar, 1);
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,109 +1,108 @@
|
|||
<template>
|
||||
<Page @loaded="onPageLoad" actionBarHidden="true">
|
||||
<GridLayout rows="*, auto" columns="auto, *">
|
||||
<Page @loaded="pgLoad" actionBarHidden="true">
|
||||
<RGridLayout :rtl="RTL" rows="*, auto" columns="auto, *">
|
||||
<OptionsList title="rest" :items="items" :action="resetListItems" />
|
||||
<GridLayout
|
||||
:hidden="toast"
|
||||
row="1"
|
||||
class="appbar"
|
||||
@loaded="onAppBarLoad"
|
||||
class="appbar rtl"
|
||||
@loaded="abLoad"
|
||||
columns="auto, *"
|
||||
>
|
||||
<Button class="ico" :text="icon.back" @tap="$navigateBack()" />
|
||||
</GridLayout>
|
||||
<Toast :toast="toast" :action="hideToast" />
|
||||
</GridLayout>
|
||||
<Toast :onload="tbLoad" :toast="toast" :action="hideToast" />
|
||||
</RGridLayout>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Observable, CoreTypes } from "@nativescript/core";
|
||||
import { Observable } from "@nativescript/core";
|
||||
import { localize } from "@nativescript/localize";
|
||||
import { mapState, mapActions } from "vuex";
|
||||
import * as utils from "~/shared/utils";
|
||||
import OptionsList from "../sub/OptionsList";
|
||||
import Toast from "../sub/Toast";
|
||||
let barTimer;
|
||||
|
||||
export default {
|
||||
components: { OptionsList, Toast },
|
||||
data() {
|
||||
return {
|
||||
toast: null,
|
||||
appbar: null,
|
||||
toast: 0,
|
||||
appbar: 0,
|
||||
toastbar: 0,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(["icon"]),
|
||||
...mapState(["icon", "RTL"]),
|
||||
items() {
|
||||
return [
|
||||
{},
|
||||
{
|
||||
type: "list",
|
||||
icon: "reset",
|
||||
rtl: 1,
|
||||
title: "restCuiL",
|
||||
data: "cuisines",
|
||||
},
|
||||
{
|
||||
type: "list",
|
||||
icon: "reset",
|
||||
rtl: 1,
|
||||
title: "restCatL",
|
||||
data: "categories",
|
||||
},
|
||||
{
|
||||
type: "list",
|
||||
icon: "reset",
|
||||
rtl: 1,
|
||||
title: "restYUL",
|
||||
data: "yieldUnits",
|
||||
},
|
||||
{
|
||||
type: "list",
|
||||
icon: "reset",
|
||||
rtl: 1,
|
||||
title: "restUL",
|
||||
data: "units",
|
||||
},
|
||||
{},
|
||||
{
|
||||
type: "info",
|
||||
title: "restInfo",
|
||||
},
|
||||
{},
|
||||
];
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions(["resetListItemsAction"]),
|
||||
onPageLoad({ object }) {
|
||||
pgLoad({ object }) {
|
||||
object.bindingContext = new Observable();
|
||||
},
|
||||
onAppBarLoad({ object }) {
|
||||
abLoad({ object }) {
|
||||
this.appbar = object;
|
||||
},
|
||||
tbLoad({ object }) {
|
||||
this.toastbar = object;
|
||||
},
|
||||
// RESET
|
||||
resetListItems(listName) {
|
||||
this.resetListItemsAction(listName);
|
||||
this.showToast();
|
||||
},
|
||||
showToast() {
|
||||
this.toast = localize("restDone");
|
||||
utils.timer(5, (val) => {
|
||||
if (!val) this.toast = val;
|
||||
this.animateBar(this.appbar, 0).then(() => {
|
||||
this.toast = localize("restDone");
|
||||
this.animateBar(this.toastbar, 1);
|
||||
});
|
||||
utils.timer(5, (val) => !val && this.hideToast());
|
||||
},
|
||||
hideToast({ object }) {
|
||||
this.appbar.translateY = 64;
|
||||
object
|
||||
.animate({
|
||||
opacity: 0,
|
||||
translate: { x: 0, y: 64 },
|
||||
duration: 250,
|
||||
curve: CoreTypes.AnimationCurve.ease,
|
||||
})
|
||||
.then(() => {
|
||||
this.showUndo = false;
|
||||
this.toast = null;
|
||||
this.appbar.animate({
|
||||
translate: { x: 0, y: 0 },
|
||||
duration: 250,
|
||||
curve: CoreTypes.AnimationCurve.ease,
|
||||
});
|
||||
object.opacity = 1;
|
||||
object.translateY = 0;
|
||||
});
|
||||
hideToast() {
|
||||
this.animateBar(this.toastbar, 0).then(() => {
|
||||
this.toast = null;
|
||||
this.animateBar(this.appbar, 1);
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,42 +1,57 @@
|
|||
<template>
|
||||
<ListView colSpan="2" rowSpan="2" class="options-list" for="item in items">
|
||||
<ListView colSpan="2" rowSpan="2" class="options" for="item in items">
|
||||
<v-template if="$index == 0">
|
||||
<Label class="pageTitle" :text="title | L" />
|
||||
</v-template>
|
||||
<v-template if="item.type == 'switch'">
|
||||
<GridLayout
|
||||
<RGridLayout
|
||||
:rtl="RTL"
|
||||
columns="auto, *, auto"
|
||||
class="option"
|
||||
@touch="touch($event, item.data, item.action)"
|
||||
>
|
||||
<Label class="ico" :text="icon[item.icon]" />
|
||||
<StackLayout col="1" verticalAlignment="center">
|
||||
<Label :text="item.title | L" class="info" />
|
||||
<Label v-if="item.subTitle" :text="item.subTitle | L" class="sub" />
|
||||
<Label class="ico rtl" :text="icon[item.icon]" />
|
||||
<StackLayout col="1" class="info">
|
||||
<RLabel :text="item.title | L" class="tw" />
|
||||
<RLabel
|
||||
v-if="item.subTitle"
|
||||
:text="item.subTitle | L"
|
||||
class="sub tw"
|
||||
/>
|
||||
</StackLayout>
|
||||
<Switch
|
||||
@loaded="swLoad"
|
||||
isUserInteractionEnabled="false"
|
||||
:color="item.checked ? '#ff5200' : '#adb5bd'"
|
||||
col="2"
|
||||
:checked="item.checked"
|
||||
/>
|
||||
</GridLayout>
|
||||
</RGridLayout>
|
||||
</v-template>
|
||||
<v-template if="item.type == 'list'">
|
||||
<GridLayout
|
||||
<RGridLayout
|
||||
:rtl="RTL"
|
||||
columns="auto, *"
|
||||
class="option"
|
||||
@touch="touch($event, item.data, item.action)"
|
||||
>
|
||||
<Label class="ico" :text="icon[item.icon]" />
|
||||
<StackLayout col="1">
|
||||
<Label :text="item.title | L" class="info" />
|
||||
<Label v-if="item.subTitle" :text="item.subTitle" class="sub" />
|
||||
<Label class="ico" :class="{ rtl: item.rtl }" :text="icon[item.icon]" />
|
||||
<StackLayout col="1" class="info">
|
||||
<RLabel :text="item.title | L" class="tw" />
|
||||
<RLabel
|
||||
:hidden="!item.subTitle"
|
||||
:text="item.subTitle"
|
||||
class="sub tw"
|
||||
/>
|
||||
</StackLayout>
|
||||
</GridLayout>
|
||||
</RGridLayout>
|
||||
</v-template>
|
||||
<v-template if="item.type == 'info'">
|
||||
<Label class="group-info sub tw" :text="item.title | L" />
|
||||
<Label
|
||||
class="group-info sub tw"
|
||||
:class="{ r: RTL }"
|
||||
:text="item.title | L"
|
||||
/>
|
||||
</v-template>
|
||||
<v-template>
|
||||
<StackLayout class="listSpace"> </StackLayout>
|
||||
|
@ -46,13 +61,19 @@
|
|||
|
||||
<script>
|
||||
import { mapState } from "vuex";
|
||||
import * as utils from "~/shared/utils";
|
||||
|
||||
export default {
|
||||
props: ["title", "items", "action"],
|
||||
computed: {
|
||||
...mapState(["icon"]),
|
||||
...mapState(["icon", "RTL"]),
|
||||
},
|
||||
methods: {
|
||||
swLoad({ object }) {
|
||||
object.android.setRotation(
|
||||
this.RTL && utils.sysRTL() ? 0 : this.RTL || utils.sysRTL() ? 180 : 0
|
||||
);
|
||||
},
|
||||
touch({ object, action }, data, localAction) {
|
||||
object.className = action.match(/down|move/) ? "option fade" : "option";
|
||||
if (action == "up") localAction ? localAction(data) : this.action(data);
|
||||
|
|
|
@ -1,23 +1,25 @@
|
|||
<template>
|
||||
<GridLayout
|
||||
<RGridLayout
|
||||
:rtl="RTL"
|
||||
row="1"
|
||||
class="appbar snackBar"
|
||||
columns="auto, *, auto"
|
||||
@swipe="action"
|
||||
@loaded="onload"
|
||||
>
|
||||
<Button :text="count" class="ico countdown tb" />
|
||||
<Label class="title" col="1" :text="msg | L" />
|
||||
<Button class="ico fab" :text="icon.undo" @tap="undo" col="3" />
|
||||
</GridLayout>
|
||||
<Button @tap="action" :text="count" class="ico countdown tb" />
|
||||
<RLabel @tap="action" class="title" col="1" :text="msg | L" />
|
||||
<Button class="ico fab rtl" :text="icon.undo" @tap="undo" col="3" />
|
||||
</RGridLayout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from "vuex";
|
||||
|
||||
export default {
|
||||
props: ["count", "msg", "undo", "action"],
|
||||
props: ["count", "msg", "undo", "action", "onload"],
|
||||
computed: {
|
||||
...mapState(["icon"]),
|
||||
...mapState(["icon", "RTL"]),
|
||||
},
|
||||
};
|
||||
</script>
|
|
@ -1,193 +1,280 @@
|
|||
<template>
|
||||
<GridLayout
|
||||
<RGridLayout
|
||||
:rtl="RTL"
|
||||
rows="auto, auto"
|
||||
columns="auto, *, auto, auto, auto"
|
||||
class="singleTimer"
|
||||
class="timer"
|
||||
>
|
||||
<!-- :class="{ blink: done }" -->
|
||||
<Button
|
||||
class="ico"
|
||||
class="ico min rtl"
|
||||
:text="done ? icon.ring : timer.isPaused ? icon.start : icon.pause"
|
||||
@tap="!done && toggleProgress()"
|
||||
/>
|
||||
<StackLayout col="1" class="info" :colSpan="timer.isPaused ? 1 : 2">
|
||||
<Label :text="timer.label" class="tb title tw" />
|
||||
<Label
|
||||
@touch="!timer.recipeID && touch($event)"
|
||||
<StackLayout
|
||||
col="1"
|
||||
class="info"
|
||||
:colSpan="timer.isPaused || !timer.preset ? 1 : 2"
|
||||
>
|
||||
<RLabel :text="timer.label" class="tb title tw a" />
|
||||
<RLabel
|
||||
:hidden="!timer.recipeID && done"
|
||||
@touch="!done && touch($event)"
|
||||
:text="getRecipeTitle"
|
||||
class="recipeTitle"
|
||||
:class="timer.recipeID ? 'sub' : 'clickable'"
|
||||
class="a"
|
||||
:class="timer.recipeID ? 'sub' : 'accent'"
|
||||
/>
|
||||
<RLabel
|
||||
:text="
|
||||
progress == 0
|
||||
? countUp
|
||||
? getCount
|
||||
: formattedTime(timer.time)
|
||||
: getCount
|
||||
"
|
||||
/>
|
||||
<Label :text="formattedTime(timer.time)" />
|
||||
</StackLayout>
|
||||
<Button
|
||||
col="2"
|
||||
class="ico"
|
||||
:hidden="(!timer.isPaused || progress == 0) && !done"
|
||||
:text="icon.reset"
|
||||
@tap="resetTimer"
|
||||
class="ico rtl"
|
||||
:hidden="(!timer.isPaused && timer.preset) || done || countUp"
|
||||
:text="isReset || timer.preset ? icon.reset : icon.addTo"
|
||||
@tap="isReset || timer.preset ? resetTimer() : addPreset()"
|
||||
/>
|
||||
<Button
|
||||
col="3"
|
||||
class="ico"
|
||||
:hidden="timer.preset && !done"
|
||||
@tap="done ? delay() : addPreset()"
|
||||
:text="done ? icon.delay : icon.addTo"
|
||||
@tap="countUp ? addPreset() : addDelay()"
|
||||
:text="countUp ? icon.addTo : icon.delay"
|
||||
/>
|
||||
<Button
|
||||
col="4"
|
||||
class="ico x"
|
||||
class="ico min"
|
||||
:text="icon.x"
|
||||
@tap="removeTimerItem(timerIndex, false)"
|
||||
@tap="removeTimer(timer.id, done)"
|
||||
/>
|
||||
<Progress row="1" colSpan="5" :value="progress" />
|
||||
</GridLayout>
|
||||
<Progress @loaded="pLoaded" row="1" colSpan="5" />
|
||||
</RGridLayout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ApplicationSettings, Application } from "@nativescript/core";
|
||||
import { ApplicationSettings } from "@nativescript/core";
|
||||
import { localize } from "@nativescript/localize";
|
||||
import { mapState, mapActions } from "vuex";
|
||||
import ActionWithSearch from "../modals/ActionWithSearch";
|
||||
import ViewRecipe from "../ViewRecipe";
|
||||
import * as utils from "~/shared/utils";
|
||||
import { EventBus } from "~/main";
|
||||
|
||||
import { EvtBus } from "~/main";
|
||||
export default {
|
||||
props: [
|
||||
"timer",
|
||||
"timerIndex",
|
||||
"formattedTime",
|
||||
"removeTimer",
|
||||
"addToPreset",
|
||||
"togglePause",
|
||||
"fireTimer",
|
||||
"timerAlert",
|
||||
"showToast",
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
pBar: 0,
|
||||
count: 0,
|
||||
delay: 0,
|
||||
progress: 0,
|
||||
timerInt: this.timer.timerInterval,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(["icon", "recipes", "timerDelay"]),
|
||||
...mapState(["icon", "recipes", "timerDelay", "timerPresets", "RTL"]),
|
||||
getRecipeTitle() {
|
||||
let { recipeID } = this.timer;
|
||||
if (recipeID) {
|
||||
let recipe = this.recipes.filter(
|
||||
(e) => e.id === this.timer.recipeID
|
||||
)[0];
|
||||
return recipe
|
||||
? recipe.title
|
||||
: `[ ${this.$options.filters.L("resNF")} ]`;
|
||||
let recipe = this.recipes.filter((e) => e.id == this.timer.recipeID)[0];
|
||||
if (recipe) return recipe.title;
|
||||
else {
|
||||
this.timer.recipeID = null;
|
||||
return localize("fwr");
|
||||
}
|
||||
} else return localize("fwr");
|
||||
},
|
||||
done() {
|
||||
return this.progress >= 100;
|
||||
return this.timer.done;
|
||||
},
|
||||
getTimeInSec() {
|
||||
countUp() {
|
||||
return this.timer.mode == 0;
|
||||
},
|
||||
isReset() {
|
||||
return this.timer.isPaused && this.progress != 0;
|
||||
},
|
||||
getTotalTime() {
|
||||
return this.delay + this.actualTime;
|
||||
},
|
||||
actualTime() {
|
||||
let t = this.timer.time.split(":");
|
||||
return +t[0] * 60 * 60 + +t[1] * 60 + +t[2];
|
||||
},
|
||||
getCount() {
|
||||
let c = this.count;
|
||||
let s = Math.abs(c);
|
||||
return (
|
||||
(c < 0 ? "-" : "") +
|
||||
new Date(s * 1000)
|
||||
.toISOString()
|
||||
.slice(
|
||||
s < 10
|
||||
? 18
|
||||
: s < 60
|
||||
? 17
|
||||
: s < 600
|
||||
? 15
|
||||
: s < 3600
|
||||
? 14
|
||||
: s < 36000
|
||||
? 12
|
||||
: s < 86400
|
||||
? 11
|
||||
: 0,
|
||||
19
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions(["removeActiveTimer", "updateActiveTimer", "addTimerPreset"]),
|
||||
...mapActions([
|
||||
"removeActiveTimer",
|
||||
"addTimerPreset",
|
||||
"deleteTimerPreset",
|
||||
"sortActiveTimers",
|
||||
]),
|
||||
pLoaded({ object }) {
|
||||
this.pBar = object.android;
|
||||
this.pBar.setRotation(
|
||||
this.RTL && utils.sysRTL() ? 0 : this.RTL || utils.sysRTL() ? 180 : 0
|
||||
);
|
||||
this.initTimer();
|
||||
},
|
||||
viewRecipe(recipeID) {
|
||||
this.$navigateTo(ViewRecipe, {
|
||||
props: {
|
||||
recipeID,
|
||||
},
|
||||
});
|
||||
},
|
||||
attachRecipe() {
|
||||
this.$showModal(ActionWithSearch, {
|
||||
props: {
|
||||
title: "selRec",
|
||||
recipes: this.recipes,
|
||||
action: "aNBtn",
|
||||
},
|
||||
}).then((recipeID) => {
|
||||
let timer = this.timer;
|
||||
timer.recipeID = recipeID;
|
||||
this.updateActiveTimer(timer);
|
||||
}).then((res) => {
|
||||
if (res == "aNBtn") {
|
||||
this.$navigateTo(EditRecipe, {
|
||||
animated: false,
|
||||
});
|
||||
} else if (res) {
|
||||
let timer = this.timer;
|
||||
timer.recipeID = res;
|
||||
this.sortActiveTimers();
|
||||
}
|
||||
});
|
||||
},
|
||||
setProgress(progress, delay) {
|
||||
this.progress = progress;
|
||||
let timer = this.timer;
|
||||
if (progress <= 100 && !timer.timerInterval) {
|
||||
timer.timerInterval = setInterval(() => {
|
||||
setNum(type, val) {
|
||||
ApplicationSettings.setNumber(`${this.timer.id}${type}`, val);
|
||||
},
|
||||
setProgress() {
|
||||
this.progress = 100 - (this.count / this.getTotalTime) * 100;
|
||||
this.pBar.setProgress(this.progress, true);
|
||||
},
|
||||
initTimer() {
|
||||
this.resetInterval();
|
||||
this.setProgress();
|
||||
!this.timer.isPaused && this.pBar.setIndeterminate(this.countUp);
|
||||
if (this.progress < 100 || !this.timer.timerInt) {
|
||||
this.timer.timerInt = setInterval(() => {
|
||||
if (!this.timer.isPaused) {
|
||||
this.progress += 100 / (delay + this.getTimeInSec);
|
||||
ApplicationSettings.setNumber(
|
||||
`${this.timer.id}progress`,
|
||||
this.progress
|
||||
);
|
||||
}
|
||||
if (this.progress >= 100) {
|
||||
if (progress < 100) this.fireTimer(timer);
|
||||
clearInterval(timer.timerInterval);
|
||||
ApplicationSettings.remove(`${this.timer.id}delay`);
|
||||
this.setNum("c", this.countUp ? this.count++ : --this.count);
|
||||
this.setProgress();
|
||||
} else this.resetInterval();
|
||||
if (this.progress >= 100 && this.count >= 0) {
|
||||
this.timer.done = 1;
|
||||
this.timerAlert();
|
||||
}
|
||||
}, 1000);
|
||||
this.updateActiveTimer(timer);
|
||||
}
|
||||
},
|
||||
resetInterval() {
|
||||
let timer = this.timer;
|
||||
clearInterval(this.timer.timerInterval);
|
||||
timer.timerInterval = null;
|
||||
this.updateActiveTimer(timer);
|
||||
clearInterval(this.timer.timerInt);
|
||||
this.timer.timerInt = 0;
|
||||
this.pBar.setIndeterminate(false);
|
||||
},
|
||||
resetTimer() {
|
||||
this.resetInterval();
|
||||
this.togglePause(this.timer, true);
|
||||
ApplicationSettings.remove(`${this.timer.id}delay`);
|
||||
this.setProgress(0, 0);
|
||||
ApplicationSettings.setNumber(`${this.timer.id}progress`, 0);
|
||||
this.clearNotification();
|
||||
this.count = this.actualTime;
|
||||
this.progress = this.delay = this.timer.done = 0;
|
||||
ApplicationSettings.remove(`${this.timer.id}d`);
|
||||
this.setNum("c", this.count);
|
||||
this.toggleProgress(1);
|
||||
this.pBar.setProgress(0, true);
|
||||
},
|
||||
clearNotification() {
|
||||
Application.android.unregisterBroadcastReceiver("timer" + this.timer.id);
|
||||
utils.TimerNotif.clear(this.timer.id);
|
||||
},
|
||||
toggleProgress(bool) {
|
||||
this.togglePause(this.timer, bool);
|
||||
this.timer.isPaused
|
||||
? this.resetInterval()
|
||||
: this.setProgress(
|
||||
ApplicationSettings.getNumber(`${this.timer.id}progress`, 0),
|
||||
ApplicationSettings.getNumber(`${this.timer.id}delay`, 0)
|
||||
);
|
||||
},
|
||||
removeTimerItem(index, noUndo) {
|
||||
this.resetInterval();
|
||||
this.removeTimer(this.timer.id, index, noUndo);
|
||||
toggleProgress(n) {
|
||||
this.togglePause(this.timer, n);
|
||||
this.timer.isPaused ? this.resetInterval() : this.initTimer();
|
||||
},
|
||||
addPreset() {
|
||||
let exist = this.timerPresets.some((e) => e.id == this.timer.id);
|
||||
this.timer.preset = 1;
|
||||
this.addToPreset(this.timer);
|
||||
if (this.countUp) {
|
||||
this.timer.time = new Date(this.count * 1000)
|
||||
.toISOString()
|
||||
.substr(11, 8);
|
||||
}
|
||||
let timer = JSON.parse(JSON.stringify(this.timer));
|
||||
let { recipeID, timerInt, isPaused, preset, done, mode, ...presetTimer } =
|
||||
timer;
|
||||
this.addTimerPreset(presetTimer);
|
||||
exist ? this.showToast("prstTU") : this.showToast("aTPrst");
|
||||
},
|
||||
delay() {
|
||||
let delayInS = this.timerDelay.split(" ")[0] * 60;
|
||||
ApplicationSettings.setNumber(`${this.timer.id}delay`, delayInS);
|
||||
let progress = (100 / delayInS) * this.getTimeInSec;
|
||||
addDelay() {
|
||||
this.timer.done = 0;
|
||||
let td = this.timerDelay;
|
||||
let delayDur =
|
||||
this.getLocaleN(td) + " " + localize(td > 1 ? "minutes" : "minute");
|
||||
this.showToast(localize("wDBy", this.timer.label, delayDur));
|
||||
let delay = td * 60;
|
||||
if (this.done) this.delay = delay;
|
||||
else this.delay += delay;
|
||||
if (this.count >= 0) this.count += delay;
|
||||
else this.count = this.delay;
|
||||
this.setNum("d", this.delay);
|
||||
this.setNum("c", this.count);
|
||||
this.resetInterval();
|
||||
this.setProgress(progress, delayInS);
|
||||
this.clearNotification();
|
||||
this.initTimer();
|
||||
this.timerAlert();
|
||||
},
|
||||
|
||||
// HELPERS
|
||||
touch({ object, action }) {
|
||||
object.className = action.match(/down|move/)
|
||||
? "recipeTitle clickable fade"
|
||||
: "recipeTitle clickable";
|
||||
let classes = object.className;
|
||||
classes = action.match(/down|move/)
|
||||
? !classes.includes("fade")
|
||||
? classes + " fade"
|
||||
: classes
|
||||
: classes.replace(/ fade/g, "");
|
||||
if (action == "up") this.attachRecipe();
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.setProgress(
|
||||
ApplicationSettings.getNumber(`${this.timer.id}progress`, 0),
|
||||
ApplicationSettings.getNumber(`${this.timer.id}delay`, 0)
|
||||
created() {
|
||||
this.delay = ApplicationSettings.getNumber(`${this.timer.id}d`, 0);
|
||||
this.count = ApplicationSettings.getNumber(
|
||||
`${this.timer.id}c`,
|
||||
this.actualTime
|
||||
);
|
||||
EventBus.$on("timer" + this.timer.id, (e) => {
|
||||
let bID = "timer" + this.timer.id;
|
||||
EvtBus.$off(bID);
|
||||
EvtBus.$on(bID, (e) => {
|
||||
switch (e) {
|
||||
case "stop":
|
||||
this.resetTimer();
|
||||
break;
|
||||
case "delay":
|
||||
this.delay();
|
||||
this.addDelay();
|
||||
break;
|
||||
case "dismiss":
|
||||
this.removeTimer(this.timer.id, 1);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,20 +1,22 @@
|
|||
<template>
|
||||
<GridLayout
|
||||
v-show="toast"
|
||||
:hidden="!toast"
|
||||
row="1"
|
||||
colSpan="2"
|
||||
class="appbar snackBar"
|
||||
columns="*"
|
||||
@swipe="action"
|
||||
@tap="action"
|
||||
@loaded="onload"
|
||||
>
|
||||
<FlexboxLayout minHeight="48" alignItems="center">
|
||||
<Label class="title msg" :text="toast" />
|
||||
</FlexboxLayout>
|
||||
<StackLayout minHeight="48">
|
||||
<RLabel class="title msg" :text="toast" />
|
||||
</StackLayout>
|
||||
</GridLayout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ["toast", "action"],
|
||||
props: ["toast", "action", "onload"],
|
||||
};
|
||||
</script>
|
|
@ -290,13 +290,13 @@
|
|||
"yld": "Ergebnis",
|
||||
"buto": "Gesichert in %s",
|
||||
"sysDefB": "Systemstandard + schwarz",
|
||||
"tmr": "Eieruhr %s",
|
||||
"tmr": "Kurzzeitwecker %s",
|
||||
"strtBtn": "START",
|
||||
"ntmr": "Neue Eieruhr",
|
||||
"timer": "Eieruhr",
|
||||
"ntmr": "Neuer Kurzzeitwecker",
|
||||
"timer": "Kurzzeitwecker",
|
||||
"sec": "s",
|
||||
"tmrvbrt": "Eieruhrvibration",
|
||||
"tmrSnd": "Eieruhrton",
|
||||
"tmrvbrt": "Kurzzeitweckervibration",
|
||||
"tmrSnd": "Kurzzeitweckerton",
|
||||
"aTPrst": "Zu Voreinstellungen hinzugefügt",
|
||||
"fwr": "für welches Rezept?",
|
||||
"prstBtn": "Voreinstellungen",
|
||||
|
@ -308,17 +308,17 @@
|
|||
"minute": "Minute",
|
||||
"dlyDur": "Verzögerungsdauer",
|
||||
"delay": "Verzögerung",
|
||||
"tmrRm": "Eieruhr entfernt",
|
||||
"tmrRm": "Kurzzeitwecker entfernt",
|
||||
"notifSetg": "Benachrichtigungseinstellungen",
|
||||
"delPrst": "Du bist dabei, %s aus den Voreinstellungen zu löschen",
|
||||
"prsts": "Voreinstellungen",
|
||||
"ttv": "Zum Anzeigen tippen",
|
||||
"dismissAll": "Alle Eieruhren verwerfen",
|
||||
"dismissAll": "Alle Kurzzeitwecker verwerfen",
|
||||
"dismiss": "Verwerfen",
|
||||
"texp": "%s Eieruhren abgelaufen",
|
||||
"texp": "%s Kurzzeitwecker abgelaufen",
|
||||
"wDBy": "%1$s wurde um %2$s verzögert",
|
||||
"prstTU": "Voreingestellte Zeit aktualisiert",
|
||||
"ccwt": "Koche selbstbewusst mit Eieruhren!",
|
||||
"ccwt": "Koche selbstbewusst mit Kurzzeitweckern!",
|
||||
"gtD": "Zu Datum gehen",
|
||||
"random": "Zufällig",
|
||||
"oAP": "%1$s laufend, %2$s angehalten",
|
||||
|
@ -333,5 +333,16 @@
|
|||
"tue": "Dienstag",
|
||||
"mon": "Montag",
|
||||
"sun": "Sonntag",
|
||||
"calVM": "Modus der Kalenderansicht"
|
||||
"calVM": "Modus der Kalenderansicht",
|
||||
"d": "Tag",
|
||||
"wk": "Woche",
|
||||
"mnth": "Monat",
|
||||
"nvr": "Nie",
|
||||
"otaw": "Älter als eine Woche",
|
||||
"otam": "Älter als ein Monat",
|
||||
"otay": "Älter als ein Jahr",
|
||||
"admp": "Mahlzeitenpläne automatisch löschen",
|
||||
"plsCrt": "Verwende die Plus-Taste, um einen zu erstellen",
|
||||
"ehwmp": "Iss gesund mit Essensplänen!",
|
||||
"selMT": "Mahlzeitentyp auswählen"
|
||||
}
|
||||
|
|
|
@ -336,5 +336,14 @@
|
|||
"cpy": "copy",
|
||||
"tdy": "Today",
|
||||
"tmrw": "Tomorrow",
|
||||
"ystr": "Yesterday"
|
||||
"ystr": "Yesterday",
|
||||
"selMT": "Select meal type",
|
||||
"ehwmp": "Eat healthy with meal plans!",
|
||||
"plsCrt": "Use the plus button to create one",
|
||||
"admp": "Auto-delete meal plans",
|
||||
"otay": "Older than a year",
|
||||
"otam": "Older than a month",
|
||||
"otaw": "Older than a week",
|
||||
"nvr": "Never",
|
||||
"add": "Add"
|
||||
}
|
||||
|
|
|
@ -333,5 +333,16 @@
|
|||
"mon": "Monday",
|
||||
"sun": "Sunday",
|
||||
"calVM": "Calendar view mode",
|
||||
"oAP": "%1$s ongoing, %2$s paused"
|
||||
"oAP": "%1$s ongoing, %2$s paused",
|
||||
"d": "Day",
|
||||
"wk": "Week",
|
||||
"mnth": "Month",
|
||||
"nvr": "Never",
|
||||
"otaw": "Older than a week",
|
||||
"otam": "Older than a month",
|
||||
"otay": "Older than a year",
|
||||
"admp": "Auto delete meal plans",
|
||||
"plsCrt": "Use the plus button to create one",
|
||||
"ehwmp": "Eat healthy with meal plans!",
|
||||
"selMT": "Select meal type"
|
||||
}
|
||||
|
|
|
@ -333,5 +333,16 @@
|
|||
"mon": "Monday",
|
||||
"sun": "Sunday",
|
||||
"calVM": "Calendar view mode",
|
||||
"oAP": "%1$s ongoing, %2$s paused"
|
||||
"oAP": "%1$s ongoing, %2$s paused",
|
||||
"d": "Day",
|
||||
"wk": "Week",
|
||||
"mnth": "Month",
|
||||
"nvr": "Never",
|
||||
"otaw": "Older than a week",
|
||||
"otam": "Older than a month",
|
||||
"otay": "Older than a year",
|
||||
"admp": "Auto delete meal plans",
|
||||
"plsCrt": "Use the plus button to create one",
|
||||
"ehwmp": "Eat healthy with meal plans!",
|
||||
"selMT": "Select meal type"
|
||||
}
|
||||
|
|
|
@ -312,14 +312,6 @@
|
|||
"tmrRm": "Temporizador eliminado",
|
||||
"delPrst": "Está a punto de eliminar %s de los preajustes",
|
||||
"prsts": "Preselecciones",
|
||||
"ttv": "Toca para ver",
|
||||
"dismissAll": "Descartar todos los temporizadores",
|
||||
"dismiss": "Descartar",
|
||||
"texp": "%s temporizadores expirados",
|
||||
"random": "Aleatorio",
|
||||
"ystr": "Ayer",
|
||||
"tmrw": "Mañana",
|
||||
"tdy": "Hoy",
|
||||
"cpy": "copia",
|
||||
"sat": "sábado",
|
||||
"fri": "viernes",
|
||||
|
@ -328,9 +320,10 @@
|
|||
"tue": "martes",
|
||||
"mon": "lunes",
|
||||
"sun": "domingo",
|
||||
"calVM": "Modo de vista del calendario",
|
||||
"oAP": "%1$s en curso, %2$s en pausa",
|
||||
"prstTU": "Hora preestablecida actualizada",
|
||||
"ccwt": "¡Cocine con confianza con los temporizadores!",
|
||||
"gtD": "Ir a la fecha"
|
||||
"d": "Día",
|
||||
"wk": "Semana",
|
||||
"mnth": "Mes",
|
||||
"ystr": "Ayer",
|
||||
"tmrw": "Mañana",
|
||||
"tdy": "Hoy"
|
||||
}
|
||||
|
|
343
app/i18n/fi.json
Normal file
|
@ -0,0 +1,343 @@
|
|||
{
|
||||
"aap": "Liitä valokuva",
|
||||
"About": "Tietoja",
|
||||
"aBtn": "LISÄÄ",
|
||||
"aD": "Valmista!",
|
||||
"addCmbBtn": "LISÄÄ YHDISTELMÄ",
|
||||
"aFBu": "Lisää resepti varmuuskopioinnin suorittamiseen",
|
||||
"aIngBtn": "LISÄÄ AINESOSA",
|
||||
"allCats": "Kaikki luokat",
|
||||
"allCuis": "Kaikki keittiöt",
|
||||
"allTs": "Kaikki tunnisteet",
|
||||
"American": "amerikkalainen",
|
||||
"aNBtn": "LISÄÄ UUSI",
|
||||
"aNoBtn": "LISÄÄ HUOMAUTUS",
|
||||
"app.name": "EnRecipes",
|
||||
"appCrd": "Jaettu EnRecipesin kautta. Lataa se F-Droidista, IzzyOnDroidista tai Play Storesta.",
|
||||
"Appetizers": "Alkupalat",
|
||||
"appInfo": "EnRecipes on avoimen lähdekoodin, yksityisyyden suojaa kunnioittava digitaalinen keittokirja, jonka avulla voit luoda, hallita ja jakaa reseptejäsi",
|
||||
"apply": "KÄYTÄ",
|
||||
"appRst": "Sovelluksen uudelleenkäynnistys vaaditaan",
|
||||
"April": "huhtikuu",
|
||||
"aStpBtn": "",
|
||||
"August": "elokuu",
|
||||
"Barbecue": "Grilli",
|
||||
"Beverages": "Juomat",
|
||||
"Black": "Musta",
|
||||
"Brazilian": "brasilialainen",
|
||||
"Breads": "Leivät",
|
||||
"breakfast": "Aamiainen",
|
||||
"British": "brittiläinen",
|
||||
"buEmp": "Varmuuskopiotiedosto on tyhjä",
|
||||
"buFol": "Varmuuskopioiden hakemisto",
|
||||
"buInc": "Virheellinen tai vioittunut varmuuskopiotiedosto",
|
||||
"buInfo": "Luo ZIP-tiedoston, joka sisältää kaikki tiedot, jotka voidaan tuoda takaisin",
|
||||
"buMod": "Varmuuskopiotiedostoa muutettiin muualla",
|
||||
"cat": "Luokka",
|
||||
"cBtn": "PERUUTA",
|
||||
"Challenging": "Haastava",
|
||||
"Chinese": "kiinalainen",
|
||||
"clove": "kynsi",
|
||||
"cm": "cm",
|
||||
"cmbs": "Yhdistelmät",
|
||||
"conBtn": "JATKA",
|
||||
"conf": "Vahvista",
|
||||
"cookT": "Kypsennysaika",
|
||||
"cPic": "Rajaa kuva",
|
||||
"Created": "Luotu",
|
||||
"cui": "Keittiö",
|
||||
"cup": "cup",
|
||||
"Cup": "Kuppi",
|
||||
"dAgo": "%s päivää sitten",
|
||||
"Danish": "tanskalainen",
|
||||
"Dark": "Tumma",
|
||||
"db": "Tietokanta",
|
||||
"dBtn": "POISTA",
|
||||
"December": "joulukuu",
|
||||
"delRecInfo": "Olet poistamassa reseptiä %s pysyvästi",
|
||||
"delRecsInfo": "Olet poistamassa %s pysyvästi",
|
||||
"Desserts": "Jälkiruoat",
|
||||
"detailed": "Yksityiskohtainen",
|
||||
"Difficulty level": "Vaikeustaso",
|
||||
"dinner": "Illallinen",
|
||||
"disBtn": "HYLKÄÄ",
|
||||
"disc": "Tässä reseptissä on tallentamattomia muutoksia. Mitä haluaisit tehdä?",
|
||||
"donate": "Lahjoita",
|
||||
"dozen": "tusina",
|
||||
"drop": "",
|
||||
"dsp": "",
|
||||
"Easy": "Helppo",
|
||||
"editRec": "Muokkaa resepti",
|
||||
"Egyptian": "egyptiläinen",
|
||||
"English": "englantilainen",
|
||||
"EnRecipes": "EnRecipes",
|
||||
"expBu": "Vie koko varmuuskopio",
|
||||
"expip": "Vienti käynnissä",
|
||||
"expSuc": "",
|
||||
"favourites": "",
|
||||
"February": "helmikuu",
|
||||
"Filipino": "",
|
||||
"Filtered recipes": "Suodatetut reseptit",
|
||||
"fl oz": "",
|
||||
"fltr": "",
|
||||
"Fluid Ounce": "",
|
||||
"French": "ranskalainen",
|
||||
"FRI": "pe",
|
||||
"fsList": "Suosikkireseptisi on lueteltu täällä",
|
||||
"g": "g",
|
||||
"gal": "",
|
||||
"Gallon": "",
|
||||
"German": "saksalainen",
|
||||
"gh": "Näytä GitHub:ssa",
|
||||
"Gram": "gramma",
|
||||
"Greek": "kreikkalainen",
|
||||
"grid": "",
|
||||
"grocery": "Ostoslista",
|
||||
"guide": "Käyttöopas",
|
||||
"Healthy": "Terveellinen",
|
||||
"hr": "t.",
|
||||
"impBu": "Tuo tietoja",
|
||||
"impFail": "Tuonti epäonnistui",
|
||||
"impInfo": "Tukee tämän sovelluksen viemiä täydellisiä varmuuskopioita",
|
||||
"impip": "Tuonti käynnissä",
|
||||
"impSuc": "Tuonti onnistui",
|
||||
"in": "",
|
||||
"Indian": "intialainen",
|
||||
"ings": "Ainekset",
|
||||
"inss": "Ohjeet",
|
||||
"intf": "Käyttöliittymä",
|
||||
"invFile": "Virheellinen tiedosto",
|
||||
"Irish": "irlantilainen",
|
||||
"it": "",
|
||||
"Italian": "",
|
||||
"Jamaican": "",
|
||||
"January": "tammikuu",
|
||||
"Japanese": "japanilainen",
|
||||
"Jewish": "juutalainen",
|
||||
"joinTG": "",
|
||||
"July": "heinäkuu",
|
||||
"June": "kesäkuu",
|
||||
"kEdit": "",
|
||||
"Kenyan": "",
|
||||
"kg": "kg",
|
||||
"Kilogram": "kilogramma",
|
||||
"Korean": "korealainen",
|
||||
"l": "l",
|
||||
"lang": "Kieli",
|
||||
"large": "",
|
||||
"Last updated": "",
|
||||
"lb": "",
|
||||
"leaf": "",
|
||||
"Light": "",
|
||||
"listVM": "",
|
||||
"Litre": "",
|
||||
"Loaf": "",
|
||||
"ltAgo": "",
|
||||
"lunch": "",
|
||||
"mAgo": "",
|
||||
"Main dishes": "",
|
||||
"March": "",
|
||||
"May": "",
|
||||
"Meat": "",
|
||||
"medium": "",
|
||||
"Mexican": "",
|
||||
"mg": "",
|
||||
"Millilitre": "",
|
||||
"min": "",
|
||||
"minimal": "",
|
||||
"ml": "",
|
||||
"Moderate": "",
|
||||
"MON": "",
|
||||
"newCui": "",
|
||||
"Newest first": "",
|
||||
"newRec": "",
|
||||
"newUnit": "",
|
||||
"Nigerian": "",
|
||||
"nLangInfo": "",
|
||||
"nNBtn": "",
|
||||
"no": "",
|
||||
"noAccSensor": "",
|
||||
"noFavs": "",
|
||||
"Noodles": "",
|
||||
"noRecs": "Hakua vastaavia reseptejä ei ole",
|
||||
"noRecsInL": "",
|
||||
"nos": "",
|
||||
"November": "marraskuu",
|
||||
"nwCat": "Uusi luokka",
|
||||
"nwYiU": "",
|
||||
"October": "lokakuu",
|
||||
"OK": "OK",
|
||||
"Oldest first": "",
|
||||
"opts": "Valinnat",
|
||||
"Ounce": "",
|
||||
"oz": "",
|
||||
"Pasta": "",
|
||||
"Patty": "",
|
||||
"photogrid": "",
|
||||
"pht": "Reseptivalokuva",
|
||||
"piece": "pala",
|
||||
"Piece": "Pala",
|
||||
"pinch": "",
|
||||
"planner": "Ateriasuunnittelija",
|
||||
"plsAdd": "Lisää resepti pluspainikkeella",
|
||||
"Portuguese": "portugalilainen",
|
||||
"Poultry": "",
|
||||
"Pound": "",
|
||||
"prepT": "Valmisteluaika",
|
||||
"priv": "Tietosuojakäytäntö",
|
||||
"pt": "",
|
||||
"qt": "",
|
||||
"Quickest first": "",
|
||||
"Rating": "",
|
||||
"rBtn": "POISTA",
|
||||
"rec": "Resepti",
|
||||
"recE": "On jo olemassa:",
|
||||
"recF": "löydettyä reseptiä",
|
||||
"recI": "",
|
||||
"recListEmp": "",
|
||||
"recPic": "Reseptivalokuva",
|
||||
"recRm": "Resepti poistettu",
|
||||
"recs": "reseptiä",
|
||||
"recTitle": "Minun terveellinen reseptini",
|
||||
"recU": "Päivitetty:",
|
||||
"req": "",
|
||||
"resNF": "",
|
||||
"rest": "Nollaa",
|
||||
"restCatL": "",
|
||||
"restCuiL": "",
|
||||
"restDone": "",
|
||||
"restInfo": "",
|
||||
"restUL": "",
|
||||
"restYUL": "",
|
||||
"Rice": "Riisi",
|
||||
"rmCatInfo": "Olet poistamassa %s luokkaluettelosta",
|
||||
"rmCmb": "Yhdistelmä poistettu",
|
||||
"rmCuiInfo": "",
|
||||
"rmIng": "Ainesosa poistettu",
|
||||
"rmIns": "Ohje poistettu",
|
||||
"rmN": "Huomautus poistettu",
|
||||
"rmUInfo": "",
|
||||
"rmYUInfo": "",
|
||||
"Roll": "",
|
||||
"rp": "Poista valokuva",
|
||||
"rst": "UUDELLEENKÄYNNISTÄ",
|
||||
"Russian": "venäläinen",
|
||||
"Salads": "Salaatit",
|
||||
"SAT": "la",
|
||||
"Sauces": "Kastikkeet",
|
||||
"Scottish": "skotlantilainen",
|
||||
"Seafood": "",
|
||||
"selRec": "",
|
||||
"September": "",
|
||||
"ser": "Etsi",
|
||||
"Serving": "",
|
||||
"SET": "ASETA",
|
||||
"Settings": "Asetukset",
|
||||
"shr": "Jaa",
|
||||
"Side dishes": "",
|
||||
"simple": "",
|
||||
"Slowest first": "",
|
||||
"sltd": "",
|
||||
"small": "",
|
||||
"snacks": "",
|
||||
"Soups": "Keitot",
|
||||
"Spanish": "espanjalainen",
|
||||
"Sri Lankan": "srilankalainen",
|
||||
"srpu": "Jaa reseptikuva käyttämällä…",
|
||||
"srt": "Järjestä",
|
||||
"sru": "Jaa resepti käyttämällä…",
|
||||
"stars": "",
|
||||
"stick": "",
|
||||
"stp": "",
|
||||
"strAdd": "",
|
||||
"SUN": "su",
|
||||
"sVw": "Ravista nähdäksesi satunnainen resepti",
|
||||
"sVwInfo": "Auttaa sinua valitsemaan, mitä valmistaa, kun et osaa päättää",
|
||||
"Swedish": "ruotsalainen",
|
||||
"swm": "Aloita viikko maanantaina",
|
||||
"sysDef": "Järjestelmän oletus",
|
||||
"Tablespoon": "",
|
||||
"tbsp": "",
|
||||
"Teaspoon": "",
|
||||
"Thai": "thaimaalainen",
|
||||
"Theme": "Teema",
|
||||
"THU": "to",
|
||||
"title": "Otsikko",
|
||||
"tLInfo": "Reseptit, joita haluat kokeilla myöhemmin, on lueteltu täällä",
|
||||
"today": "tänään",
|
||||
"triedInfo": "Kokeilit tätä reseptiä %s",
|
||||
"trnsl": "Käännä",
|
||||
"trylater": "",
|
||||
"trySer": "ETSI KAIKISTA RESEPTEISTÄ?",
|
||||
"ts": "Tunnisteet",
|
||||
"tsInfo": "",
|
||||
"tsp": "",
|
||||
"TUE": "ti",
|
||||
"Turkish": "",
|
||||
"Undefined": "Määrittelemätön",
|
||||
"unit": "",
|
||||
"Unit": "",
|
||||
"unsaved": "",
|
||||
"untRec": "",
|
||||
"Vegan": "Vegaani",
|
||||
"Vegetarian": "Kasvissyöjä",
|
||||
"Vietnamese": "vietnamilainen",
|
||||
"wAgo": "%s viikkoa sitten",
|
||||
"WED": "ke",
|
||||
"yesterday": "eilen",
|
||||
"yieldQ": "",
|
||||
"yieldU": "",
|
||||
"yld": "",
|
||||
"buto": "",
|
||||
"sysDefB": "Järjestelmän oletusarvo + Musta",
|
||||
"tmr": "Ajastin %s",
|
||||
"stop": "Pysäytä",
|
||||
"ntmr": "Uusi ajastin",
|
||||
"timer": "Keittoajastin",
|
||||
"tmrSnd": "Ajastinääni",
|
||||
"aTPrst": "Lisätty esiasetuksiin",
|
||||
"fwr": "mitä reseptiä varten?",
|
||||
"prstBtn": "ESIASETUKSET",
|
||||
"sec": "s",
|
||||
"dlyDur": "Viiveen kesto",
|
||||
"seconds": "sekuntia",
|
||||
"hours": "tuntia",
|
||||
"minutes": "minuuttia",
|
||||
"hour": "tunti",
|
||||
"minute": "minuutti",
|
||||
"prsts": "Esiasetukset",
|
||||
"texp": "%s ajastinta on vanhentunut",
|
||||
"tmrRm": "Ajastin poistettu",
|
||||
"ccwt": "Keitä luottavaisesti ajastimien avulla!",
|
||||
"gtD": "Siirry päivämäärään",
|
||||
"random": "Satunnainen",
|
||||
"notifSetg": "Ilmoitusasetukset",
|
||||
"prstTU": "Esiasetettu aika päivitetty",
|
||||
"ttv": "Napauta nähdäksesi",
|
||||
"dismissAll": "Hylkää kaikki ajastimet",
|
||||
"dismiss": "Hylkää",
|
||||
"d": "Päivä",
|
||||
"wk": "Viikko",
|
||||
"mnth": "Kuukausi",
|
||||
"ystr": "Eilen",
|
||||
"tmrw": "Huomenna",
|
||||
"tdy": "Tänään",
|
||||
"cpy": "kopio",
|
||||
"sat": "lauantai",
|
||||
"fri": "perjantai",
|
||||
"thu": "torstai",
|
||||
"wed": "keskiviikko",
|
||||
"tue": "tiistai",
|
||||
"mon": "maanantai",
|
||||
"sun": "sunnuntai",
|
||||
"calVM": "Kalenterinäkymätila",
|
||||
"oAP": "%1$s käynnissä, %2$s keskeytetty",
|
||||
"ehwmp": "Syö terveellisesti ateriasuunnitelmien avulla!",
|
||||
"selMT": "Valitse ateriatyyppi",
|
||||
"plsCrt": "Käytä plus-painiketta luodaksesi yhden",
|
||||
"nvr": "Ei koskaan",
|
||||
"otaw": "Viikon jälkeen",
|
||||
"otam": "Kuukauden jälkeen",
|
||||
"otay": "Vuoden jälkeen",
|
||||
"admp": "Poista ateriasuunnitelmat automaattisesti"
|
||||
}
|
|
@ -323,7 +323,7 @@
|
|||
"random": "Aléatoire",
|
||||
"ystr": "Hier",
|
||||
"tmrw": "Demain",
|
||||
"tdy": "Oggi",
|
||||
"tdy": "Aujourd’hui",
|
||||
"cpy": "copie",
|
||||
"sat": "samedi",
|
||||
"fri": "vendredi",
|
||||
|
@ -332,6 +332,17 @@
|
|||
"tue": "mardi",
|
||||
"mon": "lundi",
|
||||
"sun": "dimanche",
|
||||
"d": "Jour",
|
||||
"wk": "Semaine",
|
||||
"mnth": "Mois",
|
||||
"calVM": "Mode d’affichage du calendrier",
|
||||
"oAP": "%1$s en cours, %2$s en pause"
|
||||
"oAP": "%1$s en cours, %2$s en pause",
|
||||
"otaw": "Après une semaine",
|
||||
"otam": "Après un mois",
|
||||
"otay": "Après un an",
|
||||
"admp": "Supprimer automatiquement les planifications de repas",
|
||||
"nvr": "Jamais",
|
||||
"plsCrt": "Utilisez le bouton plus pour en créer une",
|
||||
"ehwmp": "Mangez sainement grâce aux planifications de repas !",
|
||||
"selMT": "Sélectionnez le type de repas"
|
||||
}
|
||||
|
|
|
@ -321,9 +321,9 @@
|
|||
"ccwt": "Cuisinez avec confiance avec des minuteries!",
|
||||
"gtD": "Aller à la date",
|
||||
"random": "Aléatoire",
|
||||
"tdy": "Aujourd’hui",
|
||||
"ystr": "Hier",
|
||||
"tmrw": "Demain",
|
||||
"tdy": "Aujourd’hui",
|
||||
"cpy": "copie",
|
||||
"sat": "samedi",
|
||||
"fri": "vendredi",
|
||||
|
@ -332,6 +332,17 @@
|
|||
"tue": "mardi",
|
||||
"mon": "lundi",
|
||||
"sun": "dimanche",
|
||||
"d": "Jour",
|
||||
"wk": "Semaine",
|
||||
"mnth": "Mois",
|
||||
"calVM": "Mode d’affichage du calendrier",
|
||||
"oAP": "%1$s en cours, %2$s en pause"
|
||||
"oAP": "%1$s en cours, %2$s en pause",
|
||||
"otaw": "Après une semaine",
|
||||
"otam": "Après un mois",
|
||||
"otay": "Après un an",
|
||||
"admp": "Supprimer automatiquement les planifications de repas",
|
||||
"nvr": "Jamais",
|
||||
"plsCrt": "Utilisez le bouton plus pour en créer une",
|
||||
"ehwmp": "Mangez sainement grâce aux planifications de repas!",
|
||||
"selMT": "Sélectionnez le type de repas"
|
||||
}
|
||||
|
|
|
@ -323,7 +323,7 @@
|
|||
"random": "Aléatoire",
|
||||
"ystr": "Hier",
|
||||
"tmrw": "Demain",
|
||||
"tdy": "Oggi",
|
||||
"tdy": "Aujourd’hui",
|
||||
"cpy": "copie",
|
||||
"sat": "samedi",
|
||||
"fri": "vendredi",
|
||||
|
@ -332,6 +332,17 @@
|
|||
"tue": "mardi",
|
||||
"mon": "lundi",
|
||||
"sun": "dimanche",
|
||||
"d": "Jour",
|
||||
"wk": "Semaine",
|
||||
"mnth": "Mois",
|
||||
"calVM": "Mode d’affichage du calendrier",
|
||||
"oAP": "%1$s en cours, %2$s en pause"
|
||||
"oAP": "%1$s en cours, %2$s en pause",
|
||||
"nvr": "Jamais",
|
||||
"otaw": "Après une semaine",
|
||||
"otam": "Après un mois",
|
||||
"otay": "Après un an",
|
||||
"admp": "Supprimer automatiquement les planifications de repas",
|
||||
"plsCrt": "Utilisez le bouton plus pour en créer une",
|
||||
"ehwmp": "Mangez sainement grâce aux planifications de repas!",
|
||||
"selMT": "Sélectionnez le type de repas"
|
||||
}
|
||||
|
|
|
@ -321,9 +321,9 @@
|
|||
"ccwt": "Cuisinez avec confiance avec des minuteries !",
|
||||
"gtD": "Aller à la date",
|
||||
"random": "Aléatoire",
|
||||
"tdy": "Aujourd’hui",
|
||||
"ystr": "Hier",
|
||||
"tmrw": "Demain",
|
||||
"tdy": "Aujourd’hui",
|
||||
"cpy": "copie",
|
||||
"sat": "samedi",
|
||||
"fri": "vendredi",
|
||||
|
@ -332,6 +332,17 @@
|
|||
"tue": "mardi",
|
||||
"mon": "lundi",
|
||||
"sun": "dimanche",
|
||||
"d": "Jour",
|
||||
"wk": "Semaine",
|
||||
"mnth": "Mois",
|
||||
"calVM": "Mode d’affichage du calendrier",
|
||||
"oAP": "%1$s en cours, %2$s en pause"
|
||||
"oAP": "%1$s en cours, %2$s en pause",
|
||||
"otaw": "Après une semaine",
|
||||
"otam": "Après un mois",
|
||||
"otay": "Après un an",
|
||||
"admp": "Supprimer automatiquement les planifications de repas",
|
||||
"nvr": "Jamais",
|
||||
"plsCrt": "Utilisez le bouton plus pour en créer une",
|
||||
"ehwmp": "Mangez sainement grâce aux planifications de repas !",
|
||||
"selMT": "Sélectionnez le type de repas"
|
||||
}
|
||||
|
|
|
@ -332,6 +332,17 @@
|
|||
"tue": "martedì",
|
||||
"mon": "lunedì",
|
||||
"sun": "domenica",
|
||||
"d": "Giorno",
|
||||
"wk": "Settimana",
|
||||
"mnth": "Mese",
|
||||
"calVM": "Modalità di visualizzazione calendario",
|
||||
"oAP": "%1$s in corso, %2$s in pausa"
|
||||
"oAP": "%1$s in corso, %2$s in pausa",
|
||||
"otaw": "Dopo una settimana",
|
||||
"otam": "Dopo un mese",
|
||||
"otay": "Dopo un anno",
|
||||
"nvr": "Mai",
|
||||
"admp": "Elimina automaticamente i piani pasto",
|
||||
"plsCrt": "Usa il pulsante più per crearne uno",
|
||||
"ehwmp": "Mangia sano con i piani dei pasti!",
|
||||
"selMT": "Seleziona il tipo di pasto"
|
||||
}
|
||||
|
|
293
app/i18n/ja.json
Normal file
|
@ -0,0 +1,293 @@
|
|||
{
|
||||
"aap": "写真を添付",
|
||||
"About": "アプリについて",
|
||||
"aBtn": "追加",
|
||||
"aD": "完了しました!",
|
||||
"addCmbBtn": "組合せを追加",
|
||||
"aFBu": "バックアップするにはレシピを登録してください",
|
||||
"aIngBtn": "材料を追加",
|
||||
"allCats": "全てのカテゴリー",
|
||||
"allCuis": "全てのジャンル",
|
||||
"allTs": "全てのタグ",
|
||||
"American": "アメリカ料理",
|
||||
"aNBtn": "新しく追加",
|
||||
"aNoBtn": "メモを追加",
|
||||
"app.name": "EnRecipes",
|
||||
"appCrd": "EnRecipesから共有されました。F-DroidかIzzyOnDroidかPlayストアからダウンロード出来ます。",
|
||||
"Appetizers": "前菜",
|
||||
"appInfo": "EnRecipesはレシピを作成・管理・共有することができる、オープンソースでプライバシーに配慮したデジタル料理本です",
|
||||
"apply": "適用する",
|
||||
"appRst": "アプリの再起動が必要",
|
||||
"April": "4月",
|
||||
"aStpBtn": "手順を追加",
|
||||
"August": "8月",
|
||||
"Barbecue": "キャンプ料理",
|
||||
"Beverages": "飲物",
|
||||
"Black": "黒",
|
||||
"Brazilian": "ブラジル料理",
|
||||
"Breads": "パン",
|
||||
"breakfast": "朝食",
|
||||
"British": "イギリス料理",
|
||||
"buEmp": "バックアップファイルが空です",
|
||||
"buFol": "バックアップフォルダー",
|
||||
"buInc": "バックアップファイルが壊れています",
|
||||
"buInfo": "全てのデータを復元するためのZIPファイルを生成します",
|
||||
"buMod": "バックアップファイルが一部修正されています",
|
||||
"cat": "カテゴリー",
|
||||
"cBtn": "キャンセル",
|
||||
"Challenging": "難しい",
|
||||
"Chinese": "中華料理",
|
||||
"clove": "クローブ",
|
||||
"cm": "cm",
|
||||
"cmbs": "組合せ",
|
||||
"conBtn": "続ける",
|
||||
"conf": "確認",
|
||||
"cookT": "調理時間",
|
||||
"cPic": "写真を切り抜く",
|
||||
"Created": "作成日時",
|
||||
"cui": "ジャンル",
|
||||
"cup": "カップ",
|
||||
"Cup": "カップ",
|
||||
"dAgo": "%s 日前",
|
||||
"Danish": "デンマーク料理",
|
||||
"Dark": "ダーク",
|
||||
"db": "データベース",
|
||||
"dBtn": "削除",
|
||||
"December": "12月",
|
||||
"delRecInfo": "レシピ %s を削除しようとしています",
|
||||
"delRecsInfo": "%s 件のレシピを削除しようとしています",
|
||||
"Desserts": "デザート",
|
||||
"detailed": "詳細",
|
||||
"Difficulty level": "難易度",
|
||||
"dinner": "夕食",
|
||||
"disBtn": "破棄",
|
||||
"disc": "レシピの変更が保存されていません。どうしますか?",
|
||||
"donate": "寄付する",
|
||||
"dozen": "ダース",
|
||||
"drop": "滴",
|
||||
"dsp": "デザート用スプーン",
|
||||
"Easy": "簡単",
|
||||
"editRec": "レシピを編集する",
|
||||
"Egyptian": "エジプト料理",
|
||||
"English": "イングランド料理",
|
||||
"EnRecipes": "EnRecipes",
|
||||
"expBu": "バックアップをエクスポート",
|
||||
"expip": "エクスポートを実行中",
|
||||
"expSuc": "エクスポートに成功",
|
||||
"favourites": "お気に入り",
|
||||
"February": "2月",
|
||||
"Filipino": "フィリピン料理",
|
||||
"Filtered recipes": "絞り込み結果",
|
||||
"fl oz": "液量オンス",
|
||||
"fltr": "絞り込み",
|
||||
"Fluid Ounce": "液量オンス",
|
||||
"French": "フランス料理",
|
||||
"FRI": "金",
|
||||
"fsList": "お気に入りのレシピはここに表示されます",
|
||||
"g": "g",
|
||||
"gal": "ガロン",
|
||||
"Gallon": "ガロン",
|
||||
"German": "ドイツ料理",
|
||||
"gh": "GitHubで見る",
|
||||
"Gram": "グラム",
|
||||
"Greek": "ギリシャ料理",
|
||||
"grid": "グリッド",
|
||||
"grocery": "食材のリスト",
|
||||
"guide": "ユーザーガイド",
|
||||
"Healthy": "ヘルシー",
|
||||
"hr": "時間",
|
||||
"impBu": "データをインポート",
|
||||
"impFail": "インポートに失敗",
|
||||
"impInfo": "アプリからエクスポートしたフルバックアップに対応しています",
|
||||
"impip": "インポートを実行中",
|
||||
"impSuc": "インポートに成功",
|
||||
"Indian": "インド料理",
|
||||
"ings": "材料",
|
||||
"inss": "作り方",
|
||||
"intf": "インターフェイス",
|
||||
"invFile": "無効なファイルです",
|
||||
"Irish": "アイルランド料理",
|
||||
"Italian": "イタリア料理",
|
||||
"Jamaican": "ジャマイカ料理",
|
||||
"January": "1月",
|
||||
"Japanese": "和食",
|
||||
"Jewish": "ユダヤ料理",
|
||||
"joinTG": "Telegramグループに参加",
|
||||
"July": "7月",
|
||||
"June": "6月",
|
||||
"kEdit": "編集を続ける",
|
||||
"Kenyan": "ケニア料理",
|
||||
"kg": "kg",
|
||||
"Kilogram": "キログラム",
|
||||
"Korean": "韓国料理",
|
||||
"l": "リットル",
|
||||
"lang": "言語",
|
||||
"Last updated": "最終更新",
|
||||
"leaf": "枚",
|
||||
"Light": "ライト",
|
||||
"listVM": "一覧の表示方法",
|
||||
"Litre": "リットル",
|
||||
"Loaf": "ローフ",
|
||||
"ltAgo": "ずっと前",
|
||||
"lunch": "昼食",
|
||||
"mAgo": "%s か月前",
|
||||
"Main dishes": "主菜",
|
||||
"March": "3月",
|
||||
"May": "5月",
|
||||
"Meat": "肉料理",
|
||||
"Mexican": "メキシコ料理",
|
||||
"mg": "mg",
|
||||
"Millilitre": "ミリリットル",
|
||||
"min": "分",
|
||||
"minimal": "最小",
|
||||
"ml": "ml",
|
||||
"Moderate": "普通",
|
||||
"MON": "月",
|
||||
"newCui": "新しいジャンル",
|
||||
"Newest first": "新しい順",
|
||||
"newRec": "新しいレシピ",
|
||||
"newUnit": "新しい単位",
|
||||
"Nigerian": "ナイジェリア料理",
|
||||
"nLangInfo": "新しい言語を使用するためにEnRecipesを再起動",
|
||||
"no": "メモ",
|
||||
"noAccSensor": "加速度センサーが無効です",
|
||||
"noFavs": "お気に入りはまだありません",
|
||||
"Noodles": "麺",
|
||||
"noRecs": "検索に一致するレシピがありません",
|
||||
"noRecsInL": "検索に一致するレシピが見つかりませんでした",
|
||||
"nos": "メモ",
|
||||
"November": "11月",
|
||||
"nwCat": "新しいカテゴリー",
|
||||
"nwYiU": "新しい仕上がり単位",
|
||||
"October": "10月",
|
||||
"OK": "OK",
|
||||
"Oldest first": "古いもの順",
|
||||
"opts": "オプション",
|
||||
"Ounce": "オンス",
|
||||
"Pasta": "パスタ",
|
||||
"Patty": "パティ",
|
||||
"photogrid": "写真グリッド",
|
||||
"pht": "レシピの写真",
|
||||
"piece": "片",
|
||||
"Piece": "片",
|
||||
"planner": "献立プラン",
|
||||
"plsAdd": "プラスボタンを押して追加します",
|
||||
"Portuguese": "ポルトガル料理",
|
||||
"Poultry": "チキン料理",
|
||||
"Pound": "ポンド",
|
||||
"prepT": "準備時間",
|
||||
"priv": "プライバシーポリシー",
|
||||
"pt": "少々",
|
||||
"qt": "クォート",
|
||||
"Quickest first": "速いもの順",
|
||||
"Rating": "評価",
|
||||
"rBtn": "削除",
|
||||
"rec": "レシピ",
|
||||
"recE": "既に存在します:",
|
||||
"recF": "件のレシピが見つかりました",
|
||||
"recI": "インポートしました:",
|
||||
"recListEmp": "まだ何もありません!レシピを追加してもう一度試してください",
|
||||
"recPic": "レシピの写真",
|
||||
"recRm": "レシピを削除しました",
|
||||
"recs": "レシピ",
|
||||
"recTitle": "私の健康レシピ",
|
||||
"recU": "アップデート:",
|
||||
"req": "%s が必要",
|
||||
"resNF": "レシピが見つかりません",
|
||||
"rest": "リセット",
|
||||
"restCatL": "カテゴリーリストをリセット",
|
||||
"restCuiL": "ジャンルのリストをリセット",
|
||||
"restDone": "リセットが完了しました",
|
||||
"restInfo": "リストをリセットすると、作成した項目が削除され、既定の項目を復元します。既にあるレシピには影響しません。",
|
||||
"restUL": "単位のリストをリセットする",
|
||||
"restYUL": "仕上がり分量の単位のリストをリセットする",
|
||||
"Rice": "お米料理",
|
||||
"rmCatInfo": "カテゴリーのリストから %s を削除しようとしています",
|
||||
"rmCmb": "組合せが削除されました",
|
||||
"rmCuiInfo": "ジャンルのリストから %s を削除しようとしています",
|
||||
"rmIng": "材料を削除しました",
|
||||
"rmIns": "作り方を削除しました",
|
||||
"rmN": "メモが削除されました",
|
||||
"rmUInfo": "単位のリストから %s を削除しようとしています",
|
||||
"rmYUInfo": "仕上がり分量の単位のリストから %s を削除しようとしています",
|
||||
"Roll": "ロール",
|
||||
"rp": "写真を削除",
|
||||
"rst": "再起動",
|
||||
"Russian": "ロシア料理",
|
||||
"Salads": "サラダ",
|
||||
"SAT": "土",
|
||||
"Sauces": "ソース",
|
||||
"Scottish": "スコットランド料理",
|
||||
"Seafood": "シーフード",
|
||||
"selRec": "レシピを選択",
|
||||
"September": "9月",
|
||||
"ser": "検索",
|
||||
"Serving": "人前",
|
||||
"SET": "設定",
|
||||
"Settings": "設定",
|
||||
"shr": "共有",
|
||||
"Side dishes": "副菜",
|
||||
"simple": "シンプル",
|
||||
"Slowest first": "遅い順",
|
||||
"sltd": "選択",
|
||||
"snacks": "軽食",
|
||||
"Soups": "スープ",
|
||||
"Spanish": "スペイン料理",
|
||||
"Sri Lankan": "スリランカ料理",
|
||||
"srpu": "レシピの写真を共有...",
|
||||
"srt": "並び替え",
|
||||
"sru": "レシピを共有...",
|
||||
"stars": "星評価",
|
||||
"stp": "作り方",
|
||||
"strAdd": "レシピを追加しましょう!",
|
||||
"SUN": "日",
|
||||
"sVw": "振ってランダムなレシピを表示",
|
||||
"sVwInfo": "何を作るか決められないときに使います",
|
||||
"Swedish": "スウェーデン料理",
|
||||
"swm": "月曜始まりにする",
|
||||
"sysDef": "システム既定",
|
||||
"Tablespoon": "大さじ",
|
||||
"tbsp": "大さじ",
|
||||
"Teaspoon": "小さじ",
|
||||
"Thai": "タイ料理",
|
||||
"Theme": "テーマ",
|
||||
"THU": "木",
|
||||
"title": "タイトル",
|
||||
"tLInfo": "あとで試したいレシピはここに並びます",
|
||||
"today": "今日",
|
||||
"triedInfo": "に作りました",
|
||||
"trnsl": "翻訳",
|
||||
"trylater": "あとで作る",
|
||||
"trySer": "全てのレシピを検索しますか?",
|
||||
"ts": "タグ",
|
||||
"tsInfo": "スペースで区切ってください",
|
||||
"tsp": "小さじ",
|
||||
"TUE": "火",
|
||||
"Turkish": "トルコ料理",
|
||||
"unit": "個",
|
||||
"Unit": "単位",
|
||||
"unsaved": "未保存の変更",
|
||||
"untRec": "無題のレシピ",
|
||||
"Vegan": "ビーガン",
|
||||
"Vegetarian": "ベジタリアン",
|
||||
"Vietnamese": "ベトナム料理",
|
||||
"wAgo": "%s 週前",
|
||||
"WED": "水",
|
||||
"yesterday": "昨日",
|
||||
"yieldQ": "仕上がり分量",
|
||||
"yieldU": "仕上がり分量の単位",
|
||||
"yld": "仕上がり分量",
|
||||
"buto": "%s としてバックアップしました",
|
||||
"sysDefB": "システム既定+黒",
|
||||
"in": "中の",
|
||||
"Undefined": "未定義",
|
||||
"nNBtn": "あとで",
|
||||
"stick": "スティック",
|
||||
"pinch": "ピンチ",
|
||||
"oz": "オンス",
|
||||
"lb": "ポンド",
|
||||
"it": "材料",
|
||||
"small": "小",
|
||||
"large": "大",
|
||||
"medium": "中"
|
||||
}
|
293
app/i18n/ml.json
Normal file
|
@ -0,0 +1,293 @@
|
|||
{
|
||||
"aap": "ഒരു ഫോട്ടോ അറ്റാച്ചുചെയ്യുക",
|
||||
"About": "കുറിച്ച്",
|
||||
"aBtn": "ചേർക്കുക",
|
||||
"aD": "എല്ലാം ചെയ്തു!",
|
||||
"addCmbBtn": "സംയോജനം ചേർക്കുക",
|
||||
"aFBu": "ഒരു ബാക്കപ്പ് നടത്താൻ ഒരു പാചകക്കുറിപ്പ് ചേർക്കുക",
|
||||
"aIngBtn": "ചേരുവ ചേർക്കുക",
|
||||
"allCats": "എല്ലാ വിഭാഗങ്ങളും",
|
||||
"allCuis": "എല്ലാ പാചകരീതികളും",
|
||||
"allTs": "എല്ലാ ടാഗുകളും",
|
||||
"American": "അമേരിക്കൻ",
|
||||
"aNBtn": "പുതിയത് ചേർക്കുക",
|
||||
"aNoBtn": "കുറിപ്പ് ചേര്ക്കുക",
|
||||
"app.name": "ൻന്റെസിപിഎസ്",
|
||||
"appCrd": "എന്റെരെസിപീസ് വഴി പങ്കിട്ടു. എഫ്-ആൻഡ്രോയിഡ്, ഇസിഓൺഡ്രോയിഡ് അല്ലെങ്കിൽ പ്ലേ സ്റ്റോറിൽ ഇത് നേടുക.",
|
||||
"Appetizers": "വിശപ്പ്",
|
||||
"appInfo": "നിങ്ങളുടെ പാചകക്കുറിപ്പുകൾ സൃഷ്ടിക്കാനും നിയന്ത്രിക്കാനും പങ്കിടാനും അനുവദിക്കുന്ന ഒരു ഓപ്പൺ സോഴ്സ്, സ്വകാര്യത കേന്ദ്രീകരിച്ച ഡിജിറ്റൽ പാചകപുസ്തകമാണ് എന്റെരെസിപീസ്",
|
||||
"apply": "പ്രയോഗിക്കുക",
|
||||
"appRst": "അപ്ലിക്കേഷൻ പുനരാരംഭിക്കൽ ആവശ്യമാണ്",
|
||||
"April": "ഏപ്രിൽ",
|
||||
"aStpBtn": "നിർദ്ദേശം ചേർക്കുക",
|
||||
"August": "ഓഗസ്റ്റ്",
|
||||
"Barbecue": "ബാർബിക്യൂ",
|
||||
"Beverages": "പാനീയങ്ങൾ",
|
||||
"Black": "കറുപ്പ്",
|
||||
"Brazilian": "ബ്രസീലിയൻ",
|
||||
"Breads": "ബ്രെഡുകൾ",
|
||||
"breakfast": "പ്രഭാതഭക്ഷണം",
|
||||
"British": "ബ്രിട്ടീഷ്",
|
||||
"buEmp": "ബാക്കപ്പ് ഫയൽ ശൂന്യമാണ്",
|
||||
"buFol": "ബാക്കപ്പ് ഫോൾഡർ",
|
||||
"buInc": "കേടായ അല്ലെങ്കിൽ കേടായ ബാക്കപ്പ് ഫയൽ",
|
||||
"buInfo": "തിരികെ ഇറക്കുമതി ചെയ്യാൻ കഴിയുന്ന നിങ്ങളുടെ എല്ലാ ഡാറ്റയും അടങ്ങിയ ഒരു ZIP ഫയൽ സൃഷ്ടിക്കുന്നു",
|
||||
"buMod": "ബാക്കപ്പ് ഫയൽ മറ്റെവിടെയെങ്കിലും പരിഷ്ക്കരിച്ചു",
|
||||
"cat": "വിഭാഗം",
|
||||
"cBtn": "റദ്ദാക്കുക",
|
||||
"Challenging": "വെല്ലുവിളിനിറഞ്ഞ",
|
||||
"Chinese": "ചൈനീസ്",
|
||||
"clove": "ഗ്രാമ്പൂ",
|
||||
"cm": "സെന്റിമീറ്റർ",
|
||||
"cmbs": "സംയോജനങ്ങൾ",
|
||||
"conBtn": "തുടരുക",
|
||||
"conf": "സ്ഥിരീകരിക്കുക",
|
||||
"cookT": "പാചക സമയം",
|
||||
"cPic": "ഫോട്ടോ എഡിറ്റുചെയ്യുക",
|
||||
"Created": "സൃഷ്ടിച്ചു",
|
||||
"cui": "പാചകരീതി",
|
||||
"cup": "കപ്പ്",
|
||||
"Cup": "കപ്പ്",
|
||||
"dAgo": "%s ദിവസം മുമ്പ്",
|
||||
"Danish": "ഡാനിഷ്",
|
||||
"Dark": "ഇരുണ്ടത്",
|
||||
"db": "ഡാറ്റാബേസ്",
|
||||
"dBtn": "ഇല്ലാതാക്കുക",
|
||||
"December": "ഡിസംബർ",
|
||||
"delRecInfo": "%s പാചകക്കുറിപ്പ് നിങ്ങൾ ശാശ്വതമായി ഇല്ലാതാക്കാൻ പോകുന്നു",
|
||||
"delRecsInfo": "നിങ്ങൾ %s ശാശ്വതമായി ഇല്ലാതാക്കാൻ പോകുന്നു",
|
||||
"Desserts": "മധുരപലഹാരങ്ങൾ",
|
||||
"detailed": "വിശദമായ",
|
||||
"Difficulty level": "വൈഷമ്യ നില",
|
||||
"dinner": "അത്താഴം",
|
||||
"disBtn": "നിരസിക്കുക",
|
||||
"disc": "ഈ പാചകക്കുറിപ്പിൽ സംരക്ഷിക്കാത്ത മാറ്റങ്ങളുണ്ട്. നിങ്ങൾ എന്താണ് ചെയ്യാൻ ആഗ്രഹിക്കുന്നത്?",
|
||||
"donate": "സംഭാവനചെയ്യുക",
|
||||
"dozen": "ഡസൻ",
|
||||
"drop": "തുള്ളി",
|
||||
"dsp": "ഡെസേർട്ട് സ്പൂൺ",
|
||||
"Easy": "എളുപ്പമാണ്",
|
||||
"editRec": "പാചകക്കുറിപ്പ് എഡിറ്റുചെയ്യുക",
|
||||
"Egyptian": "ഈജിപ്ഷ്യൻ",
|
||||
"English": "ഇംഗ്ലീഷ്",
|
||||
"EnRecipes": "ൻന്റെസിപിഎസ്",
|
||||
"expBu": "പൂർണ്ണ ബാക്കപ്പ് എക്സ്പോർട്ടുചെയ്യുക",
|
||||
"expip": "കയറ്റുമതി പുരോഗതിയിലാണ്",
|
||||
"expSuc": "കയറ്റുമതി വിജയം",
|
||||
"favourites": "പ്രിയങ്കരങ്ങൾ",
|
||||
"February": "ഫെബ്രുവരി",
|
||||
"Filipino": "ഫിലിപ്പിനോ",
|
||||
"Filtered recipes": "ഫിൽട്ടർ ചെയ്ത പാചകക്കുറിപ്പുകൾ",
|
||||
"fl oz": "ഫ്ലൂയിഡ് un ൺസ്",
|
||||
"fltr": "ഫിൽട്ടർ ചെയ്യുക",
|
||||
"Fluid Ounce": "ഫ്ലൂയിഡ് un ൺസ്",
|
||||
"French": "ഫ്രഞ്ച്",
|
||||
"FRI": "വെള്ളി",
|
||||
"fsList": "നിങ്ങളുടെ പ്രിയപ്പെട്ട പാചകക്കുറിപ്പുകൾ ഇവിടെ പട്ടികപ്പെടുത്തിയിട്ടുണ്ട്",
|
||||
"g": "ഗ്രാം",
|
||||
"gal": "ഗാലൺ",
|
||||
"Gallon": "ഗാലൺ",
|
||||
"German": "ജർമ്മൻ",
|
||||
"gh": "GitHub- ൽ കാണുക",
|
||||
"Gram": "ഗ്രാം",
|
||||
"Greek": "ഗ്രീക്ക്",
|
||||
"grid": "ഗ്രിഡ്",
|
||||
"grocery": "പലചരക്ക് പട്ടിക",
|
||||
"guide": "ഉപയോക്തൃ ഗൈഡ്",
|
||||
"Healthy": "ആരോഗ്യമുള്ള",
|
||||
"hr": "മണിക്കൂർ",
|
||||
"impBu": "ഡാറ്റ ഇറക്കുമതി ചെയ്യുക",
|
||||
"impFail": "ഇറക്കുമതി പരാജയപ്പെട്ടു",
|
||||
"impInfo": "ഈ അപ്ലിക്കേഷൻ എക്സ്പോർട്ടുചെയ്ത പൂർണ്ണ ബാക്കപ്പുകൾ പിന്തുണയ്ക്കുന്നു",
|
||||
"impip": "ഇറക്കുമതി പുരോഗതിയിലാണ്",
|
||||
"impSuc": "ഇറക്കുമതി വിജയം",
|
||||
"in": "ഇഞ്ച്",
|
||||
"Indian": "ഇന്ത്യൻ",
|
||||
"ings": "ചേരുവകൾ",
|
||||
"inss": "നിർദ്ദേശങ്ങൾ",
|
||||
"intf": "ഇന്റർഫേസ്",
|
||||
"invFile": "അസാധുവായ ഫയൽ",
|
||||
"Irish": "ഐറിഷ്",
|
||||
"it": "ഇനം",
|
||||
"Italian": "ഇറ്റാലിയൻ",
|
||||
"Jamaican": "ജമൈക്കൻ",
|
||||
"January": "ജനുവരി",
|
||||
"Japanese": "ജാപ്പനീസ്",
|
||||
"Jewish": "ജൂതൻ",
|
||||
"joinTG": "ടെലിഗ്രാം ഗ്രൂപ്പിൽ ചേരുക",
|
||||
"July": "ജൂലൈ",
|
||||
"June": "ജൂൺ",
|
||||
"kEdit": "എഡിറ്റിംഗ് തുടരുക",
|
||||
"Kenyan": "കെനിയൻ",
|
||||
"kg": "കി. ഗ്രാം",
|
||||
"Kilogram": "കിലോഗ്രാം",
|
||||
"Korean": "കൊറിയൻ",
|
||||
"l": "ലിറ്റർ",
|
||||
"lang": "ഭാഷ",
|
||||
"large": "വലുത്",
|
||||
"Last updated": "അവസാനമായി പുതുക്കിയത്",
|
||||
"lb": "പൗണ്ട്",
|
||||
"leaf": "ഇല",
|
||||
"Light": "പ്രകാശം",
|
||||
"listVM": "പട്ടിക കാഴ്ച മോഡ്",
|
||||
"Litre": "ലിറ്റർ",
|
||||
"Loaf": "അപ്പം",
|
||||
"ltAgo": "വളരെക്കാലം മുമ്പ്",
|
||||
"lunch": "ഉച്ചഭക്ഷണം",
|
||||
"mAgo": "%s മാസം മുമ്പ്",
|
||||
"Main dishes": "പ്രധാന വിഭവങ്ങൾ",
|
||||
"March": "മാർച്ച്",
|
||||
"May": "മെയ്",
|
||||
"Meat": "മാംസം",
|
||||
"medium": "ഇടത്തരം",
|
||||
"Mexican": "മെക്സിക്കൻ",
|
||||
"mg": "മില്ലിഗ്രാം",
|
||||
"Millilitre": "മില്ലിലിറ്റർ",
|
||||
"min": "മിനിറ്റ്",
|
||||
"minimal": "കുറഞ്ഞത്",
|
||||
"ml": "മില്ലി",
|
||||
"Moderate": "മിതത്വം",
|
||||
"MON": "തിങ്കൾ",
|
||||
"newCui": "പുതിയ പാചകരീതി",
|
||||
"Newest first": "ആദ്യത്തെ പുതിയത്",
|
||||
"newRec": "പുതിയ പാചകക്കുറിപ്പ്",
|
||||
"newUnit": "പുതിയ യൂണിറ്റ്",
|
||||
"Nigerian": "നൈജീരിയൻ",
|
||||
"nLangInfo": "പുതിയ ഭാഷ ഉപയോഗിക്കുന്നതിന് എന്റെരെസിപീസ് പുനരാരംഭിക്കുക",
|
||||
"nNBtn": "ഇപ്പോൾ വേണ്ട",
|
||||
"no": "കുറിപ്പ്",
|
||||
"noAccSensor": "ആക്സിലറോമീറ്റർ സെൻസർ പ്രവർത്തനരഹിതമാക്കി അല്ലെങ്കിൽ പ്രവർത്തിക്കുന്നില്ല",
|
||||
"noFavs": "ഇതുവരെ പ്രിയപ്പെട്ട പാചകക്കുറിപ്പുകളൊന്നുമില്ല",
|
||||
"Noodles": "നൂഡിൽസ്",
|
||||
"noRecs": "പാചകക്കുറിപ്പുകളൊന്നും നിങ്ങളുടെ തിരയലുമായി പൊരുത്തപ്പെടുന്നില്ല",
|
||||
"noRecsInL": "ഇവിടെയുള്ള പാചകങ്ങളൊന്നും നിങ്ങളുടെ തിരയലുമായി പൊരുത്തപ്പെടുന്നില്ല",
|
||||
"nos": "കുറിപ്പുകൾ",
|
||||
"November": "നവംബർ",
|
||||
"nwCat": "പുതിയ വിഭാഗം",
|
||||
"nwYiU": "പുതിയ വിളവ് യൂണിറ്റ്",
|
||||
"October": "ഒക്ടോബർ",
|
||||
"OK": "ശരി",
|
||||
"Oldest first": "ആദ്യം പഴയത്",
|
||||
"opts": "ഓപ്ഷനുകൾ",
|
||||
"Ounce": "Un ൺസ്",
|
||||
"oz": "oun ൺസ്",
|
||||
"Pasta": "പാസ്ത",
|
||||
"Patty": "പാറ്റി",
|
||||
"photogrid": "ഫോട്ടോ ഗ്രിഡ്",
|
||||
"pht": "പാചകക്കുറിപ്പ് ഫോട്ടോ",
|
||||
"piece": "കഷണം",
|
||||
"Piece": "പീസ്",
|
||||
"pinch": "നുള്ള്",
|
||||
"planner": "ഭക്ഷണ പ്ലാനർ",
|
||||
"plsAdd": "ഒരെണ്ണം ചേർക്കാൻ പ്ലസ് ബട്ടൺ ഉപയോഗിക്കുക",
|
||||
"Portuguese": "പോർച്ചുഗീസ്",
|
||||
"Poultry": "കോഴി",
|
||||
"Pound": "പൗണ്ട്",
|
||||
"prepT": "തയ്യാറാക്കൽ സമയം",
|
||||
"priv": "സ്വകാര്യതാ നയം",
|
||||
"pt": "പിന്റ്",
|
||||
"qt": "ക്വാർട്ട്",
|
||||
"Quickest first": "ആദ്യ വേഗത്തിലുള്ളത്",
|
||||
"Rating": "റേറ്റിംഗ്",
|
||||
"rBtn": "നീക്കംചെയ്യുക",
|
||||
"rec": "പാചകക്കുറിപ്പ്",
|
||||
"recE": "നിലവിലുള്ളത്:",
|
||||
"recF": "പാചകക്കുറിപ്പുകൾ കണ്ടെത്തി",
|
||||
"recI": "ഇറക്കുമതി ചെയ്തത്:",
|
||||
"recListEmp": "ഇവിടെ ഒന്നുമില്ല! കുറച്ച് പാചകക്കുറിപ്പുകൾ ചേർത്ത് വീണ്ടും ശ്രമിക്കുക",
|
||||
"recPic": "പാചകക്കുറിപ്പ് ഫോട്ടോ",
|
||||
"recRm": "പാചകക്കുറിപ്പ് നീക്കംചെയ്തു",
|
||||
"recs": "പാചകക്കുറിപ്പുകൾ",
|
||||
"recTitle": "എന്റെ ആരോഗ്യകരമായ പാചകക്കുറിപ്പ്",
|
||||
"recU": "അപ്ഡേറ്റുചെയ്തത്:",
|
||||
"req": "ആവശ്യമായ %s",
|
||||
"resNF": "പാചകക്കുറിപ്പ് കണ്ടെത്തിയില്ല",
|
||||
"rest": "പുനഃക്രമീകരിക്കുക",
|
||||
"restCatL": "വിഭാഗ ലിസ്റ്റ് പുന .സജ്ജമാക്കുക",
|
||||
"restCuiL": "പാചകരീതി പട്ടിക പുന .സജ്ജമാക്കുക",
|
||||
"restDone": "പുന .സജ്ജീകരണം പൂർത്തിയായി",
|
||||
"restInfo": "ഒരു ലിസ്റ്റ് പുന .സജ്ജമാക്കുന്നത് ഉപയോക്താവ് സൃഷ്ടിച്ച എൻട്രികൾ ഇല്ലാതാക്കുകയും സ്ഥിരസ്ഥിതി എൻട്രികൾ പുന restore സ്ഥാപിക്കുകയും ചെയ്യും. നിലവിലുള്ള പാചകത്തെ ബാധിക്കില്ല.",
|
||||
"restUL": "യൂണിറ്റ് ലിസ്റ്റ് പുന .സജ്ജമാക്കുക",
|
||||
"restYUL": "വിളവ് യൂണിറ്റ് ലിസ്റ്റ് പുന .സജ്ജമാക്കുക",
|
||||
"Rice": "അരി",
|
||||
"rmCatInfo": "നിങ്ങൾ കാറ്റഗറി ലിസ്റ്റിൽ നിന്ന് %s നീക്കംചെയ്യാൻ പോകുന്നു",
|
||||
"rmCmb": "കോമ്പിനേഷൻ നീക്കംചെയ്തു",
|
||||
"rmCuiInfo": "നിങ്ങൾ പാചക പട്ടികയിൽ നിന്ന് %s നീക്കംചെയ്യാൻ പോകുന്നു",
|
||||
"rmIng": "ചേരുവ നീക്കംചെയ്തു",
|
||||
"rmIns": "നിർദ്ദേശം നീക്കംചെയ്തു",
|
||||
"rmN": "കുറിപ്പ് നീക്കംചെയ്തു",
|
||||
"rmUInfo": "നിങ്ങൾ %s യെ യൂണിറ്റ് പട്ടികയിൽ നിന്ന് നീക്കംചെയ്യാൻ പോവുകയാണ്",
|
||||
"rmYUInfo": "വിളവ് യൂണിറ്റ് പട്ടികയിൽ നിന്ന് നിങ്ങൾ %s നീക്കംചെയ്യാൻ പോകുന്നു",
|
||||
"Roll": "റോൾ",
|
||||
"rp": "ഫോട്ടോ നീക്കംചെയ്യുക",
|
||||
"rst": "പുനരാരംഭിക്കുക",
|
||||
"Russian": "റഷ്യൻ",
|
||||
"Salads": "സലാഡുകൾ",
|
||||
"SAT": "ശനി",
|
||||
"Sauces": "സോസുകൾ",
|
||||
"Scottish": "സ്കോട്ടിഷ്",
|
||||
"Seafood": "കടൽ ഭക്ഷണം",
|
||||
"selRec": "പാചകക്കുറിപ്പ് തിരഞ്ഞെടുക്കുക",
|
||||
"September": "സെപ്റ്റംബർ",
|
||||
"ser": "തിരയുക",
|
||||
"Serving": "സേവിക്കുന്നു",
|
||||
"SET": "സെറ്റ്",
|
||||
"Settings": "ക്രമീകരണങ്ങൾ",
|
||||
"shr": "പങ്കിടുക",
|
||||
"Side dishes": "സൈഡ് വിഭവങ്ങൾ",
|
||||
"simple": "ലളിതം",
|
||||
"Slowest first": "ആദ്യ വേഗത",
|
||||
"sltd": "തിരഞ്ഞെടുത്തു",
|
||||
"small": "ചെറുത്",
|
||||
"snacks": "ലഘുഭക്ഷണങ്ങൾ",
|
||||
"Soups": "സൂപ്പ്",
|
||||
"Spanish": "സ്പാനിഷ്",
|
||||
"Sri Lankan": "ശ്രീലങ്കൻ",
|
||||
"srpu": "പാചകക്കുറിപ്പ് ഫോട്ടോ പങ്കിടുക...",
|
||||
"srt": "അടുക്കുക",
|
||||
"sru": "പാചകക്കുറിപ്പ് പങ്കിടുക...",
|
||||
"stars": "നക്ഷത്ര റേറ്റിംഗ്",
|
||||
"stick": "വടി",
|
||||
"stp": "ഘട്ടം",
|
||||
"strAdd": "നിങ്ങളുടെ പാചകക്കുറിപ്പുകൾ ചേർക്കാൻ ആരംഭിക്കുക!",
|
||||
"SUN": "ഞായ",
|
||||
"sVw": "ക്രമരഹിതമായ പാചകക്കുറിപ്പ് കാണാൻ കുലുക്കുക",
|
||||
"sVwInfo": "നിങ്ങൾക്ക് തീരുമാനിക്കാൻ കഴിയാത്തപ്പോൾ എന്താണ് പാചകം ചെയ്യേണ്ടതെന്ന് തിരഞ്ഞെടുക്കാൻ നിങ്ങളെ സഹായിക്കുന്നു",
|
||||
"Swedish": "സ്വീഡിഷ്",
|
||||
"swm": "ആഴ്ചയിലെ ആദ്യ ദിവസം തിങ്കളാഴ്ച",
|
||||
"sysDef": "സിസ്റ്റം സ്ഥിരസ്ഥിതി",
|
||||
"Tablespoon": "ടേബിൾസ്പൂൺ",
|
||||
"tbsp": "ടേബിൾസ്പൂൺ",
|
||||
"Teaspoon": "ടീസ്പൂൺ",
|
||||
"Thai": "തായ്",
|
||||
"Theme": "തീം",
|
||||
"THU": "വ്യാഴം",
|
||||
"title": "ശീർഷകം",
|
||||
"tLInfo": "നിങ്ങൾ പിന്നീട് ശ്രമിക്കാൻ ആഗ്രഹിക്കുന്ന പാചകക്കുറിപ്പുകൾ ഇവിടെ പട്ടികപ്പെടുത്തിയിട്ടുണ്ട്",
|
||||
"today": "ഇന്ന്",
|
||||
"triedInfo": "നിങ്ങൾ %s ഈ പാചകക്കുറിപ്പ് പരീക്ഷിച്ചു",
|
||||
"trnsl": "വിവർത്തനം ചെയ്യുക",
|
||||
"trylater": "പിന്നീട് ശ്രമിക്കുക",
|
||||
"trySer": "എല്ലാ പാചകക്കുറിപ്പുകളിലും തിരയണോ?",
|
||||
"ts": "ടാഗുകൾ",
|
||||
"tsInfo": "സ്പെയ്സുകൾ ഉപയോഗിച്ച് വേർതിരിക്കുക",
|
||||
"tsp": "ടീസ്പൂൺ",
|
||||
"TUE": "ചൊവ്വ",
|
||||
"Turkish": "ടർക്കിഷ്",
|
||||
"Undefined": "നിർവചിച്ചിട്ടില്ല",
|
||||
"unit": "യൂണിറ്റ്",
|
||||
"Unit": "യൂണിറ്റ്",
|
||||
"unsaved": "സംരക്ഷിക്കാത്ത മാറ്റങ്ങൾ",
|
||||
"untRec": "ശീർഷകമില്ലാത്ത പാചകക്കുറിപ്പ്",
|
||||
"Vegan": "വെഗാൻ",
|
||||
"Vegetarian": "വെജിറ്റേറിയൻ",
|
||||
"Vietnamese": "വിയറ്റ്നാമീസ്",
|
||||
"wAgo": "%s ആഴ്ച മുമ്പ്",
|
||||
"WED": "ബുധൻ",
|
||||
"yesterday": "ഇന്നലെ",
|
||||
"yieldQ": "വിളവ് അളവ്",
|
||||
"yieldU": "വിളവ് യൂണിറ്റ്",
|
||||
"yld": "വരുമാനം",
|
||||
"buto": "%s ലേക്ക് ബാക്കപ്പ് ചെയ്തു",
|
||||
"sysDefB": "സിസ്റ്റം സ്ഥിരസ്ഥിതി + കറുപ്പ്"
|
||||
}
|
|
@ -332,6 +332,17 @@
|
|||
"tue": "dinsdag",
|
||||
"mon": "maandag",
|
||||
"sun": "zondag",
|
||||
"d": "Dag",
|
||||
"wk": "Week",
|
||||
"mnth": "Maand",
|
||||
"calVM": "Weergavemodus van kalender",
|
||||
"oAP": "%1$s lopende; %2$s onderbroken"
|
||||
"oAP": "%1$s lopende; %2$s onderbroken",
|
||||
"nvr": "Nooit",
|
||||
"otaw": "Ouder dan een week",
|
||||
"otam": "Ouder dan een maand",
|
||||
"otay": "Ouder dan een jaar",
|
||||
"admp": "Schema's automatisch verwijderen",
|
||||
"plsCrt": "Druk op de plusknop om een schema toe te voegen",
|
||||
"ehwmp": "Eet gezond met maaltijdschema's!",
|
||||
"selMT": "Kies het soort maaltijd"
|
||||
}
|
||||
|
|
|
@ -311,20 +311,5 @@
|
|||
"prsts": "Predefinições",
|
||||
"delPrst": "Você está prestes a apagar %s das predefinições",
|
||||
"tmrRm": "Timer removido",
|
||||
"notifSetg": "Configurações de notificação",
|
||||
"calVM": "Modo de visualização de calendário",
|
||||
"oAP": "%1$s em curso, %2$s em pausa",
|
||||
"gtD": "Ir à data",
|
||||
"random": "Aleatório",
|
||||
"ystr": "Ontem",
|
||||
"tmrw": "Amanhã",
|
||||
"tdy": "Hoje",
|
||||
"cpy": "cópia",
|
||||
"sat": "sábado",
|
||||
"fri": "sexta-feira",
|
||||
"thu": "quinta-feira",
|
||||
"wed": "quarta-feira",
|
||||
"tue": "terça-feira",
|
||||
"mon": "segunda-feira",
|
||||
"sun": "domingo"
|
||||
"notifSetg": "Configurações de notificação"
|
||||
}
|
||||
|
|
|
@ -321,17 +321,28 @@
|
|||
"ccwt": "Cozinhe com segurança com temporizadores!",
|
||||
"gtD": "Ir à data",
|
||||
"random": "Aleatória",
|
||||
"cpy": "cópia",
|
||||
"oAP": "%1$s em curso, %2$s em pausa",
|
||||
"calVM": "Modo de visualização de calendário",
|
||||
"nvr": "Nunca",
|
||||
"otaw": "Mais antigas que 1 semana",
|
||||
"otam": "Mais antigas que 1 mês",
|
||||
"otay": "Mais antigas que 1 ano",
|
||||
"admp": "Eliminar automaticamente planos de refeições",
|
||||
"plsCrt": "Use o botão + para criar uma",
|
||||
"ehwmp": "Coma saudavelmente com planificações de refeições!",
|
||||
"selMT": "Selecionar tipo de refeição",
|
||||
"ystr": "Ontem",
|
||||
"tmrw": "Amanhã",
|
||||
"tdy": "Hoje",
|
||||
"sat": "sábado",
|
||||
"fri": "sexta-feira",
|
||||
"thu": "quinta-feira",
|
||||
"wed": "quarta-feira",
|
||||
"tue": "terça-feira",
|
||||
"mon": "segunda-feira",
|
||||
"sun": "domingo"
|
||||
"cpy": "cópia",
|
||||
"sat": "Sábado",
|
||||
"fri": "Sexta-feira",
|
||||
"thu": "Quinta-feira",
|
||||
"wed": "Quarta-feira",
|
||||
"tue": "Terça-feira",
|
||||
"mon": "Segunda-feira",
|
||||
"sun": "Domingo",
|
||||
"d": "Dia",
|
||||
"wk": "Semana",
|
||||
"mnth": "Mês",
|
||||
"calVM": "Modo de vista tipo calendário",
|
||||
"oAP": "%1$s a decorrer, %2$s em pausa"
|
||||
}
|
||||
|
|
|
@ -333,5 +333,16 @@
|
|||
"mon": "திங்கள்",
|
||||
"sun": "ஞாயிறு",
|
||||
"calVM": "கேலெண்டர் காட்சி முறை",
|
||||
"oAP": "%1$s செயலில் உள்ளது,%2$s இடைநிறுத்தப்பட்டது"
|
||||
"oAP": "%1$s செயலில் உள்ளது,%2$s இடைநிறுத்தப்பட்டது",
|
||||
"d": "நாள்",
|
||||
"wk": "வாரம்",
|
||||
"mnth": "மாதம்",
|
||||
"nvr": "ஒருபோதும்",
|
||||
"otaw": "ஒரு வாரத்திற்கும் மேலானது",
|
||||
"otam": "ஒரு மாதத்திற்கும் மேலானது",
|
||||
"otay": "ஒரு வருடத்திற்கும் மேலானது",
|
||||
"admp": "உணவு திட்டங்களை தானாக நீக்கு",
|
||||
"plsCrt": "ஒன்றை உருவாக்க பிளஸ் பொத்தானைப் பயன்படுத்தவும்",
|
||||
"ehwmp": "உணவு திட்டங்களுடன் ஆரோக்கியமாக சாப்பிடுங்கள்!",
|
||||
"selMT": "உணவு வகையைத் தேர்ந்தெடுக்கவும்"
|
||||
}
|
||||
|
|
122
app/main.ts
|
@ -1,45 +1,43 @@
|
|||
import Vue from 'nativescript-vue'
|
||||
import store from './store'
|
||||
import {
|
||||
Application,
|
||||
AndroidApplication,
|
||||
ApplicationSettings,
|
||||
Utils,
|
||||
Device,
|
||||
Color,
|
||||
Frame,
|
||||
} from '@nativescript/core'
|
||||
import {
|
||||
localize,
|
||||
androidLaunchEventLocalizationHandler,
|
||||
} from '@nativescript/localize'
|
||||
import Vue from 'nativescript-vue'
|
||||
import { localize } from '@nativescript/localize'
|
||||
import EnRecipes from './components/EnRecipes.vue'
|
||||
import EditRecipe from './components/EditRecipe.vue'
|
||||
import MealPlanner from './components/MealPlanner.vue'
|
||||
import CookingTimer from './components/CookingTimer.vue'
|
||||
import GroceryList from './components/GroceryList.vue'
|
||||
import store from './store'
|
||||
|
||||
// import GroceryList from './components/GroceryList.vue'
|
||||
|
||||
import * as utils from '~/shared/utils'
|
||||
|
||||
export const EventBus = new Vue()
|
||||
export const EvtBus = new Vue()
|
||||
|
||||
let renderView: any = EnRecipes
|
||||
let renderView = EnRecipes
|
||||
|
||||
import CollectionView from '@nativescript-community/ui-collectionview/vue'
|
||||
Vue.use(CollectionView)
|
||||
import { StackLayout, GridLayout, DockLayout } from '@nativescript-rtl/ui'
|
||||
Vue.registerElement('RStackLayout', () => StackLayout)
|
||||
Vue.registerElement('RGridLayout', () => GridLayout)
|
||||
Vue.registerElement('RDockLayout', () => DockLayout)
|
||||
|
||||
import { RGridLayout, RStackLayout, RDockLayout, RLabel } from './rtl-ui'
|
||||
Vue.registerElement('RGridLayout', () => RGridLayout)
|
||||
Vue.registerElement('RStackLayout', () => RStackLayout)
|
||||
Vue.registerElement('RDockLayout', () => RDockLayout)
|
||||
Vue.registerElement('RLabel', () => RLabel)
|
||||
|
||||
import { myMixin } from './shared/mixins'
|
||||
Vue.mixin(myMixin)
|
||||
|
||||
const initFrame = () => {
|
||||
const vm = store
|
||||
|
||||
//MAIN INIT
|
||||
vm.commit('setTheme', ApplicationSettings.getString('appTheme', 'sysDef'))
|
||||
if (!vm.state.recipes.length) vm.commit('initRecipes')
|
||||
// MainInit
|
||||
vm.commit('setTheme', ApplicationSettings.getString('theme', 'sysDef'))
|
||||
vm.commit('initRecipes')
|
||||
vm.commit('initMealPlans')
|
||||
vm.commit('initListItems')
|
||||
vm.commit('initTimerPresets')
|
||||
|
@ -50,42 +48,11 @@ const initFrame = () => {
|
|||
hasTimerSound ? JSON.parse(hasTimerSound) : utils.getTones().defaultTone
|
||||
)
|
||||
}
|
||||
|
||||
// INIT FRAME
|
||||
const View = android.view.View as any
|
||||
// InitFrame
|
||||
const window = Application.android.startActivity.getWindow()
|
||||
const decorView = window.getDecorView()
|
||||
let sdkv = parseInt(Device.sdkVersion)
|
||||
function setColors(color) {
|
||||
window.setStatusBarColor(new Color(color).android)
|
||||
sdkv >= 27 && window.setNavigationBarColor(new Color(color).android)
|
||||
}
|
||||
switch (vm.state.appTheme) {
|
||||
case 'Light':
|
||||
setColors('#f1f3f5')
|
||||
break
|
||||
case 'Dark':
|
||||
setColors('#212529')
|
||||
break
|
||||
default:
|
||||
setColors('#000000')
|
||||
break
|
||||
}
|
||||
if (sdkv >= 27)
|
||||
decorView.setSystemUiVisibility(
|
||||
vm.state.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(
|
||||
vm.state.appTheme == 'Light'
|
||||
? View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
|
||||
: View.SYSTEM_UI_FLAG_DARK_STATUS_BAR
|
||||
)
|
||||
Frame.topmost().className = store.state.appTheme
|
||||
utils.setBarColors(window, decorView, vm.state.theme)
|
||||
Frame.topmost().className = vm.state.theme
|
||||
}
|
||||
const showOverLockscreen = () => {
|
||||
let ctx = Utils.ad.getApplicationContext()
|
||||
|
@ -103,12 +70,9 @@ const showOverLockscreen = () => {
|
|||
}
|
||||
}
|
||||
const intentListener = ({ intent, android }: any) => {
|
||||
console.log(intent, android)
|
||||
let action = ((intent || android).getStringExtra('action') ||
|
||||
(android && android.getAction())) as string
|
||||
|
||||
if (action) {
|
||||
console.log(action)
|
||||
switch (action) {
|
||||
case 'new_recipe':
|
||||
renderView = EditRecipe
|
||||
|
@ -118,30 +82,47 @@ const intentListener = ({ intent, android }: any) => {
|
|||
break
|
||||
case 'timer':
|
||||
renderView = CookingTimer
|
||||
Vue.navigateTo(CookingTimer as any, {
|
||||
animated: false,
|
||||
})
|
||||
break
|
||||
case 'grocery':
|
||||
renderView = GroceryList
|
||||
switch (ApplicationSettings.getNumber('isTimer', 0)) {
|
||||
case 0:
|
||||
// Closing all modals if available before navigation
|
||||
let modals = Frame.topmost()._getRootModalViews()
|
||||
for (let i = modals.length - 1; i >= 0; i--) {
|
||||
Frame.topmost()
|
||||
._getRootModalViews()
|
||||
[i].closeModal()
|
||||
}
|
||||
Vue.navigateTo(CookingTimer as any, {
|
||||
animated: false,
|
||||
})
|
||||
ApplicationSettings.setNumber('isTimer', 1)
|
||||
break
|
||||
case 2:
|
||||
Vue.navigateBack()
|
||||
break
|
||||
}
|
||||
break
|
||||
// case 'grocery':
|
||||
// renderView = GroceryList
|
||||
// break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Application.on(Application.resumeEvent, (args) => {
|
||||
console.log('App Resume')
|
||||
Application.on(Application.resumeEvent, () => {
|
||||
showOverLockscreen()
|
||||
if (
|
||||
utils.sysLocale() !==
|
||||
ApplicationSettings.getString('sysLocale', utils.sysLocale())
|
||||
) {
|
||||
Frame.reloadPage()
|
||||
utils.updateLocale()
|
||||
}
|
||||
})
|
||||
|
||||
Application.on(Application.launchEvent, (args) => {
|
||||
console.log('App Launch')
|
||||
console.log('RTL', store.state.RTL)
|
||||
utils.updateLocale()
|
||||
store.commit('setRTL')
|
||||
if (args.android) {
|
||||
androidLaunchEventLocalizationHandler()
|
||||
intentListener(args)
|
||||
}
|
||||
intentListener(args)
|
||||
Application.android.on(
|
||||
AndroidApplication.activityNewIntentEvent,
|
||||
intentListener
|
||||
|
@ -150,7 +131,6 @@ Application.on(Application.launchEvent, (args) => {
|
|||
})
|
||||
|
||||
Application.on(Application.exitEvent, () => {
|
||||
console.log('App Exit')
|
||||
renderView = EnRecipes
|
||||
Application.android.off(
|
||||
AndroidApplication.activityNewIntentEvent,
|
||||
|
|
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 938 B After Width: | Height: | Size: 938 B |
Before Width: | Height: | Size: 954 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 780 B |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 932 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 940 B |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 852 B After Width: | Height: | Size: 852 B |
Before Width: | Height: | Size: 860 B |
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
Before Width: | Height: | Size: 758 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 906 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 870 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1,016 B After Width: | Height: | Size: 1,016 B |
Before Width: | Height: | Size: 1,016 B |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 846 B |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1,018 B |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 912 B |
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 1,006 B |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 1.4 KiB |