implementing foreground service

This commit is contained in:
vishnuraghavb 2021-05-25 20:02:53 +05:30
parent 12d1d9ba3d
commit dbd08f2eb3
66 changed files with 1391 additions and 2489 deletions

51
app/ForegroundService.js Normal file
View file

@ -0,0 +1,51 @@
var ForegroundService = /** @class */ (function(_super) {
__extends(ForegroundService, _super)
function ForegroundService() {
return (_super !== null && _super.apply(this, arguments)) || this
}
ForegroundService.prototype.onStartCommand = function(
intent,
flags,
startId
) {
console.log('onStartCommand')
_super.prototype.onStartCommand.call(this, intent, flags, startId)
return android.app.Service.START_STICKY
}
ForegroundService.prototype.onCreate = function() {
console.log('onCreate')
_super.prototype.onCreate.call(this)
this.startForeground(1, this.getNotification())
}
ForegroundService.prototype.onBind = function(intent) {
return _super.prototype.onBind.call(this, intent)
}
ForegroundService.prototype.onUnbind = function(intent) {
return _super.prototype.onUnbind.call(this, intent)
}
ForegroundService.prototype.onDestroy = function() {
console.log('onDestroy')
this.stopForeground(true)
}
ForegroundService.prototype.getNotification = function() {
var channel = new android.app.NotificationChannel(
'channel_01',
'ForegroundService Channel',
android.app.NotificationManager.IMPORTANCE_DEFAULT
)
var notificationManager = this.getSystemService(
android.content.Context.NOTIFICATION_SERVICE
)
notificationManager.createNotificationChannel(channel)
var builder = new android.app.Notification.Builder(
this.getApplicationContext(),
'channel_01'
)
return builder.build()
}
ForegroundService = __decorate(
[JavaProxy('com.tns.ForegroundService')],
ForegroundService
)
return ForegroundService
})(android.app.Service)

View file

@ -16,7 +16,7 @@
@tap="$navigateTo(CTSettings)"
/>
</GridLayout>
<SingleTimer
<Timer
v-for="(timer, i) in activeTimers"
:key="timer.id"
ref="singleTimer"
@ -41,22 +41,19 @@
<Button class="ico" :text="icon.back" @tap="$navigateBack()" />
<Button class="ico fab" :text="icon.plus" @tap="addTimer" col="2" />
</GridLayout>
<GridLayout
row="1"
class="appbar snackBar"
:hidden="!showUndo"
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>
<SnackBar
:hidden="!showUndo || toast"
:count="countdown"
:msg="snackMsg"
:undo="undoDel"
:action="hideBar"
/>
<Toast :toast="toast" :action="hideBar" />
</GridLayout>
</Page>
</template>
<script>
<script lang="ts">
import { localize } from "@nativescript/localize";
import {
Observable,
@ -64,20 +61,25 @@ import {
Application,
ApplicationSettings,
AndroidApplication,
Utils,
} from "@nativescript/core";
import { mapState, mapActions } from "vuex";
import CTSettings from "./Settings/CTSettings.vue";
import ActionDialog from "./modal/ActionDialog.vue";
import CookingTimePicker from "./modal/CookingTimePicker.vue";
import CookingTimer from "./CookingTimer.vue";
import SingleTimer from "./SingleTimer.vue";
import * as utils from "~/shared/utils";
import Action from "./modals/Action.vue";
import CookingTimer from "./CookingTimer.vue";
import CTSettings from "./settings/CTSettings.vue";
import TimePickerHMS from "./modals/TimePickerHMS.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 { fgs } from "~/foreground.android";
import { EventBus } from "~/main";
let undoTimer;
export default {
components: { SingleTimer },
components: { Timer, Toast, SnackBar },
props: ["recipeID"],
data() {
return {
@ -88,6 +90,7 @@ export default {
showUndo: false,
undo: false,
CTSettings: CTSettings,
toast: null,
};
},
computed: {
@ -111,9 +114,8 @@ export default {
"addTimerPreset",
"updateActiveTimer",
]),
onPageLoad(args) {
const page = args.object;
page.bindingContext = new Observable();
onPageLoad({ object }) {
object.bindingContext = new Observable();
this.setComponent("CookingTimer");
},
onAppBarLoad({ object }) {
@ -170,17 +172,17 @@ export default {
let pausedCount = this.activeTimers.filter((e) => e.isPaused).length;
let ongoingCount = activeCount - pausedCount;
console.log("notifying");
utils.TimerNotification.show({
utils.TimerNotif.show({
bID: "bringToFront",
cID: "CookingTimer",
cName: "Cooking Timer",
cID: "cti",
cName: "Cooking Timer info",
description: `${ongoingCount} ongoing, ${pausedCount} paused`,
nID: 999,
priority: 0,
priority: -2,
sound: null,
title: localize("timer"),
});
if (activeCount <= 0) utils.TimerNotification.clear(999);
if (activeCount <= 0) utils.TimerNotif.clear(999);
},
intentListener({ intent, android }) {
let ct = "CookingTimer";
@ -191,10 +193,11 @@ export default {
let openTimer = setInterval(() => {
if (comp == ct) clearInterval(openTimer);
else {
this.$navigateTo(CookingTimer);
if (comp == "CTSettings") this.$navigateBack();
else this.$navigateTo(CookingTimer);
comp = ct;
}
// Application.off(Application.launchEvent, this.intentListener);
Application.off(Application.launchEvent, this.intentListener);
Application.android.off(
AndroidApplication.activityNewIntentEvent,
this.intentListener
@ -210,11 +213,11 @@ export default {
let title = timer.label;
let time = this.formattedTime(timer.time);
let bID = "timer" + timer.id;
utils.TimerNotification.show({
utils.TimerNotif.show({
actions: true,
bID,
cID: "FiringTimers",
cName: "Firing timers",
cID: "cta",
cName: "Cooking Timer alerts",
description: time,
nID: timer.id,
priority: 1,
@ -228,10 +231,18 @@ export default {
EventBus.$emit(bID, action);
});
},
startForegroundService() {
const ctx = Utils.ad.getApplicationContext();
const intent = new android.content.Intent();
intent.setClassName(ctx, "com.tns.ForegroundService");
ctx.startService(intent);
},
// DATA HANDLERS
addTimer() {
this.$showModal(CookingTimePicker, {
// fgs.class
this.startForegroundService();
this.$showModal(TimePickerHMS, {
props: {
title: "ntmr",
label: `${localize("tmr", this.activeTimers.length + 1)}`,
@ -244,7 +255,7 @@ export default {
let list = this.timerPresets.map(
(e) => `${e.label} - ${this.formattedTime(e.time)}`
);
this.$showModal(ActionDialog, {
this.$showModal(Action, {
props: {
title: "tmrPrsts",
list,
@ -285,7 +296,7 @@ export default {
removeTimer(id, index, noUndo) {
let temp = this.activeTimers[index];
this.removeActiveTimer(index);
utils.TimerNotification.clear(id);
utils.TimerNotif.clear(id);
if (!noUndo) {
this.showUndoBar("tmrClr")
.then(() => {
@ -306,6 +317,7 @@ export default {
timer.recipeID = timer.timerInterval = null;
timer.preset = 1;
this.addTimerPreset(timer);
this.showToast("aTPrst");
},
togglePause(timer, bool) {
if (typeof bool === "boolean") timer.isPaused = bool;
@ -313,6 +325,12 @@ export default {
this.updateActiveTimer(timer);
this.notifyTimers();
},
showToast(data) {
this.toast = localize(data);
utils.timer(5, (val) => {
if (!val) this.toast = val;
});
},
showUndoBar(message) {
return new Promise((resolve, reject) => {
clearTimeout(undoTimer);
@ -335,7 +353,8 @@ export default {
}, 100);
});
},
hideUndoBar({ object }) {
hideBar({ object }) {
this.appbar.translateY = 64;
object
.animate({
opacity: 0,
@ -345,7 +364,7 @@ export default {
})
.then(() => {
this.showUndo = false;
this.appbar.translateY = 64;
this.toast = null;
this.appbar.animate({
translate: { x: 0, y: 0 },
duration: 250,
@ -366,7 +385,7 @@ export default {
},
},
created() {
// Application.on(Application.launchEvent, this.intentListener);
Application.on(Application.launchEvent, this.intentListener);
Application.android.on(
AndroidApplication.activityNewIntentEvent,
this.intentListener

View file

@ -267,7 +267,15 @@
/>
<ActivityIndicator col="2" v-if="saving" :busy="saving" />
</GridLayout>
<GridLayout
<SnackBar
:hidden="!showUndo"
colSpan="2"
:count="countdown"
:msg="snackMsg"
:undo="undoDel"
:action="hideUndoBar"
/>
<!-- <GridLayout
row="1"
class="appbar snackBar"
:hidden="!showUndo"
@ -278,7 +286,7 @@
<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> -->
</GridLayout>
</Page>
</template>
@ -300,14 +308,18 @@ import {
import { localize } from "@nativescript/localize";
import { ImageCropper } from "nativescript-imagecropper";
import { mapState, mapActions } from "vuex";
import ActionDialog from "./modal/ActionDialog.vue";
import ActionDialogWithSearch from "./modal/ActionDialogWithSearch.vue";
import ConfirmDialog from "./modal/ConfirmDialog.vue";
import PromptDialog from "./modal/PromptDialog.vue";
import TimePicker from "./modal/TimePicker.vue";
import Action from "./modals/Action";
import ActionWithSearch from "./modals/ActionWithSearch";
import Confirm from "./modals/Confirm";
import Prompt from "./modals/Prompt";
import TimePickerHM from "./modals/TimePickerHM";
import * as utils from "~/shared/utils";
import SnackBar from "./sub/SnackBar";
let undoTimer;
export default {
components: {
SnackBar,
},
props: [
"recipeID",
"filterFavourites",
@ -384,9 +396,8 @@ export default {
"addListItemAction",
"unSyncCombinationsAction",
]),
onPageLoad(args) {
const page = args.object;
page.bindingContext = new Observable();
onPageLoad({ object }) {
object.bindingContext = new Observable();
this.hijackBackEvent();
},
onPageUnload() {
@ -424,7 +435,7 @@ export default {
this.clearEmptyFields(true);
if (this.recipe.image) {
this.modalOpen = true;
this.$showModal(ActionDialog, {
this.$showModal(Action, {
props: {
title: "recPic",
list: ["aap", "rp"],
@ -488,7 +499,7 @@ export default {
// DATA LIST
showCuisine(focus) {
this.modalOpen = true;
this.$showModal(ActionDialog, {
this.$showModal(Action, {
props: {
title: "cui",
list: this.cuisines,
@ -496,7 +507,7 @@ export default {
},
}).then((action) => {
if (action == "aNBtn") {
this.$showModal(PromptDialog, {
this.$showModal(Prompt, {
props: {
title: "newCui",
action: "aBtn",
@ -526,7 +537,7 @@ export default {
},
showCategories(focus) {
this.modalOpen = true;
this.$showModal(ActionDialog, {
this.$showModal(Action, {
props: {
title: "cat",
list: this.categories,
@ -534,7 +545,7 @@ export default {
},
}).then((action) => {
if (action == "aNBtn") {
this.$showModal(PromptDialog, {
this.$showModal(Prompt, {
props: {
title: "nwCat",
action: "aBtn",
@ -564,7 +575,7 @@ export default {
},
showYieldUnits(focus) {
this.modalOpen = true;
this.$showModal(ActionDialog, {
this.$showModal(Action, {
props: {
title: "yieldU",
list: this.yieldUnits,
@ -572,7 +583,7 @@ export default {
},
}).then((action) => {
if (action == "aNBtn") {
this.$showModal(PromptDialog, {
this.$showModal(Prompt, {
props: {
title: "nwYiU",
action: "aBtn",
@ -602,7 +613,7 @@ export default {
},
showDifficultyLevel(focus) {
this.modalOpen = true;
this.$showModal(ActionDialog, {
this.$showModal(Action, {
props: {
title: "Difficulty level",
list: this.difficultyLevels,
@ -620,7 +631,7 @@ export default {
},
showUnits(e, focus, index) {
this.modalOpen = true;
this.$showModal(ActionDialog, {
this.$showModal(Action, {
props: {
title: "Unit",
list: this.units,
@ -628,7 +639,7 @@ export default {
},
}).then((action) => {
if (action == "aNBtn") {
this.$showModal(PromptDialog, {
this.$showModal(Prompt, {
props: {
title: "newUnit",
action: "aBtn",
@ -662,7 +673,7 @@ export default {
let filteredRecipes = this.recipes.filter(
(e) => !existingCombinations.includes(e.id)
);
this.$showModal(ActionDialogWithSearch, {
this.$showModal(ActionWithSearch, {
props: {
title: "selRec",
recipes: filteredRecipes,
@ -923,7 +934,7 @@ export default {
let t = this.recipe[time].split(":");
let hr = t[0];
let min = t[1];
this.$showModal(TimePicker, {
this.$showModal(TimePickerHM, {
props: {
title: `${time == "prepTime" ? "prepT" : "cookT"}`,
action: "SET",
@ -975,7 +986,7 @@ export default {
navigateBack() {
if (this.hasChanges) {
this.modalOpen = true;
this.$showModal(ConfirmDialog, {
this.$showModal(Confirm, {
props: {
title: "unsaved",
description: localize("disc"),

View file

@ -18,7 +18,7 @@
col="1"
class="ico"
:text="icon.cog"
@tap="navigateTo(Settings, 'Settings', true)"
@tap="navigateTo(AppSettings, 'Settings', true)"
/>
</GridLayout>
</v-template>
@ -432,10 +432,10 @@ import EditRecipe from "./EditRecipe";
import MealPlanner from "./MealPlanner";
import CookingTimer from "./CookingTimer";
import GroceryList from "./GroceryList";
import Settings from "./Settings";
import ActionDialog from "./modal/ActionDialog.vue";
import ConfirmDialog from "./modal/ConfirmDialog.vue";
import Filters from "./modal/Filters.vue";
import AppSettings from "./settings/AppSettings";
import Action from "./modals/Action";
import Confirm from "./modals/Confirm";
import Filters from "./modals/Filter";
import * as utils from "~/shared/utils";
let lastTime = 0;
let lastShake = 0;
@ -456,7 +456,7 @@ export default {
scrollPos: 1,
filterFavourites: false,
filterTrylater: false,
Settings: Settings,
AppSettings: AppSettings,
MealPlanner: MealPlanner,
CookingTimer: CookingTimer,
GroceryList: GroceryList,
@ -603,9 +603,8 @@ export default {
: View.SYSTEM_UI_FLAG_DARK_STATUS_BAR
);
},
onPageLoad(args) {
const page = args.object;
page.bindingContext = new Observable();
onPageLoad({ object }) {
object.bindingContext = new Observable();
this.filterFavourites
? this.setComponent("favourites")
: this.filterTrylater
@ -685,7 +684,7 @@ export default {
openSort() {
this.showTools = false;
this.releaseBackEvent();
this.$showModal(ActionDialog, {
this.$showModal(Action, {
props: {
title: "srt",
list: [
@ -748,7 +747,7 @@ export default {
this.recipes.findIndex((e) => e.id === this.selection[0])
].title
}"`;
this.$showModal(ConfirmDialog, {
this.$showModal(Confirm, {
props: {
title: localize("conf"),
description: `${localize(
@ -1080,7 +1079,12 @@ export default {
if (!this.recipes.length) this.initRecipes();
this.initMealPlans();
this.initListItems();
if (!this.timerSound.title) this.setTimerSound(utils.getTones()[0]);
if (!this.timerSound.title) {
let hasTimerSound = ApplicationSettings.getString("timerSound", 0);
this.setTimerSound(
hasTimerSound ? JSON.parse(hasTimerSound) : utils.getTones().defaultTone
);
}
},
};
</script>

View file

@ -28,9 +28,8 @@ export default {
},
methods: {
...mapActions(["setComponent"]),
onPageLoad(args) {
const page = args.object;
page.bindingContext = new Observable();
onPageLoad({ object }) {
object.bindingContext = new Observable();
this.setComponent("GroceryList");
},
// HELPERS

View file

@ -120,17 +120,13 @@
col="3"
/>
</GridLayout>
<GridLayout
row="1"
class="appbar snackBar"
<SnackBar
:hidden="!showUndo"
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>
:count="countdown"
:msg="snackMsg"
:undo="undoDel"
:action="hideUndoBar"
/>
</GridLayout>
</Page>
</template>
@ -138,12 +134,16 @@
<script>
import { Observable, CoreTypes } from "@nativescript/core";
import { mapState, mapActions } from "vuex";
import ViewRecipe from "./ViewRecipe.vue";
import MPSettings from "./Settings/MPSettings.vue";
import ActionDialogWithSearch from "./modal/ActionDialogWithSearch.vue";
import ViewRecipe from "./ViewRecipe";
import MPSettings from "./settings/MPSettings";
import ActionWithSearch from "./modals/ActionWithSearch";
import SnackBar from "./sub/SnackBar";
let undoTimer;
export default {
components: {
SnackBar,
},
data() {
return {
mealTimes: ["breakfast", "lunch", "dinner", "snacks"],
@ -227,9 +227,8 @@ export default {
"addMealPlanAction",
"deleteMealPlanAction",
]),
onPageLoad(args) {
const page = args.object;
page.bindingContext = new Observable();
onPageLoad({ object }) {
object.bindingContext = new Observable();
this.setComponent("MealPlanner");
if (!this.today || this.today === new Date().getDate()) this.goToToday();
},
@ -342,7 +341,7 @@ export default {
let filteredRecipes = this.recipes.filter((e) =>
this.getRecipes[type] ? !this.getRecipes[type].includes(e.id) : true
);
this.$showModal(ActionDialogWithSearch, {
this.$showModal(ActionWithSearch, {
props: {
title: "selRec",
recipes: filteredRecipes,

View file

@ -1,106 +0,0 @@
<template>
<Page @loaded="onPageLoad" actionBarHidden="true">
<GridLayout rows="*, auto" columns="auto, *">
<ListView
colSpan="2"
rowSpan="2"
class="options-list"
for="item in items"
>
<v-template if="$index == 0">
<Label class="pageTitle" :text="'Settings' | L" />
</v-template>
<v-template if="$index == 6">
<StackLayout class="listSpace"> </StackLayout>
</v-template>
<v-template>
<GridLayout
columns="auto, *"
class="option"
@touch="touch($event, item.view)"
>
<Label
verticalAlignment="center"
class="ico"
:text="icon[item.icon]"
/>
<Label verticalAlignment="center" col="1" :text="item.title | L" />
</GridLayout>
</v-template>
</ListView>
<GridLayout row="1" class="appbar" rows="*" columns="auto, *">
<Button class="ico" :text="icon.back" @tap="$navigateBack()" />
</GridLayout>
</GridLayout>
</Page>
</template>
<script>
import { Observable } from "@nativescript/core";
import { mapState, mapActions } from "vuex";
import Interface from "./Settings/Interface.vue";
import Options from "./Settings/Options.vue";
import Database from "./Settings/Database.vue";
import Reset from "./Settings/Reset.vue";
import About from "./Settings/About.vue";
export default {
data() {
return {
items: [
{},
{
icon: "interface",
title: "intf",
view: Interface,
},
{
icon: "opts",
title: "opts",
view: Options,
},
{
icon: "db",
title: "db",
view: Database,
},
{
icon: "reset",
title: "rest",
view: Reset,
},
{
icon: "info",
title: "About",
view: About,
},
{},
],
};
},
computed: {
...mapState(["icon"]),
},
methods: {
...mapActions(["setComponent"]),
onPageLoad(args) {
const page = args.object;
page.bindingContext = new Observable();
this.setComponent("Settings");
},
// HELPERS
navigateTo(view) {
this.$navigateTo(view, {
transition: {
name: "slide",
duration: 200,
curve: "easeOut",
},
});
},
touch({ object, action }, view) {
object.className = action.match(/down|move/) ? "option fade" : "option";
if (action == "up") this.navigateTo(view);
},
},
};
</script>

View file

@ -1,139 +0,0 @@
<template>
<Page @loaded="onPageLoad" actionBarHidden="true">
<GridLayout rows="*, auto" columns="auto, *">
<ListView
colSpan="2"
rowSpan="2"
class="options-list"
for="item in items"
>
<v-template if="$index == 0">
<Label class="pageTitle" :text="'Settings' | L" />
</v-template>
<v-template if="item.type == 'switch'">
<GridLayout columns="auto, *, auto" class="option">
<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"
/>
</StackLayout>
<Switch
:color="item.checked ? '#ff5200' : '#adb5bd'"
col="2"
:checked="item.checked"
@checkedChange="item.action"
/>
</GridLayout>
</v-template>
<v-template if="item.type == 'list'">
<GridLayout
columns="auto, *"
class="option"
@touch="touch($event, item.action)"
>
<Label class="ico" :text="icon[item.icon]" />
<StackLayout col="1">
<Label :text="item.title | L" class="info" />
<Label :text="item.subTitle" class="sub" />
</StackLayout>
</GridLayout>
</v-template>
<v-template>
<StackLayout class="listSpace"> </StackLayout>
</v-template>
</ListView>
<GridLayout row="1" class="appbar" rows="*" columns="auto, *">
<Button class="ico" :text="icon.back" @tap="$navigateBack()" />
</GridLayout>
</GridLayout>
</Page>
</template>
<script>
import { Observable, Device } from "@nativescript/core";
import { mapState, mapActions } from "vuex";
import { localize } from "@nativescript/localize";
import ActionDialog from "../modal/ActionDialog.vue";
import * as utils from "~/shared/utils";
export default {
computed: {
...mapState(["icon", "timerDelay", "timerSound", "timerVibrate"]),
items() {
return [
{},
{
type: "list",
icon: "delay",
title: "dlyDur",
subTitle: this.timerDelay,
action: this.showDelayList,
},
{
type: "list",
icon: "sound",
title: "tmrSnd",
subTitle: this.timerSound.title,
action: this.showSoundsList,
},
{
type: "switch",
icon: "vibrate",
title: "tmrvbrt",
checked: this.timerVibrate,
action: this.toggleTimerVibrate,
},
{},
];
},
},
methods: {
...mapActions(["setTimerDelay", "setTimerSound", "setTimerVibrate"]),
onPageLoad(args) {
const page = args.object;
page.bindingContext = new Observable();
},
toggleTimerVibrate({ object }) {
this.setTimerVibrate(object.checked);
},
showDelayList() {
let list = [
...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")}`
);
this.$showModal(ActionDialog, {
props: {
title: "dlyDur",
list,
},
}).then((dur) => dur && this.setTimerDelay(dur));
},
showSoundsList() {
let tones = utils.getTones();
this.$showModal(ActionDialog, {
props: {
title: "tmrSnd",
list: tones.map((e) => e.title),
},
}).then(
(tone) =>
tone &&
tone !== this.timerSound.title &&
this.setTimerSound(tones.filter((e) => e.title === tone)[0])
);
},
// HELPERS
touch({ object, action }, method) {
object.className = action.match(/down|move/) ? "option fade" : "option";
if (action == "up") method();
},
},
};
</script>

View file

@ -1,75 +0,0 @@
<template>
<Page @loaded="onPageLoad" actionBarHidden="true">
<GridLayout rows="*, auto" columns="auto, *">
<ListView
colSpan="2"
rowSpan="2"
class="options-list"
for="item in items"
>
<v-template if="$index == 0">
<Label class="pageTitle" :text="'Settings' | L" />
</v-template>
<v-template if="item.type == 'switch'">
<GridLayout columns="auto, *, auto" class="option">
<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"
/>
</StackLayout>
<Switch
:color="item.checked ? '#ff5200' : '#adb5bd'"
col="2"
:checked="item.checked"
@checkedChange="item.action"
/>
</GridLayout>
</v-template>
<v-template>
<StackLayout class="listSpace"> </StackLayout>
</v-template>
</ListView>
<GridLayout row="1" class="appbar" rows="*" columns="auto, *">
<Button class="ico" :text="icon.back" @tap="$navigateBack()" />
</GridLayout>
</GridLayout>
</Page>
</template>
<script>
import { Observable } from "@nativescript/core";
import { mapState, mapActions } from "vuex";
export default {
computed: {
...mapState(["icon", "mondayFirst"]),
items() {
return [
{},
{
type: "switch",
icon: "week",
title: "swm",
checked: this.mondayFirst,
action: this.toggleFirstDay,
},
{},
];
},
},
methods: {
...mapActions(["setFirstDay"]),
onPageLoad(args) {
const page = args.object;
page.bindingContext = new Observable();
},
toggleFirstDay({ object }) {
this.setFirstDay(object.checked);
},
},
};
</script>

View file

@ -1,109 +0,0 @@
<template>
<Page @loaded="onPageLoad" actionBarHidden="true">
<GridLayout rows="*, auto" columns="auto, *">
<ListView
colSpan="2"
rowSpan="2"
class="options-list"
for="item in items"
>
<v-template if="$index == 0">
<Label class="pageTitle" :text="'opts' | L" />
</v-template>
<v-template if="item.type == 'switch'">
<GridLayout columns="auto, *, auto" class="option">
<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"
/>
</StackLayout>
<Switch
:color="item.checked ? '#ff5200' : '#adb5bd'"
col="2"
:checked="item.checked"
@checkedChange="item.action"
/>
</GridLayout>
</v-template>
<v-template>
<StackLayout class="listSpace"> </StackLayout>
</v-template>
</ListView>
<GridLayout
v-show="!toast"
row="1"
class="appbar"
rows="*"
columns="auto, *"
>
<Button class="ico" :text="icon.back" @tap="$navigateBack()" />
</GridLayout>
<GridLayout
v-show="toast"
row="1"
colSpan="2"
class="appbar snackBar"
columns="*"
@tap="toast = null"
>
<FlexboxLayout minHeight="48" alignItems="center">
<Label class="title msg" :text="toast" />
</FlexboxLayout>
</GridLayout>
</GridLayout>
</Page>
</template>
<script>
import { Observable } from "@nativescript/core";
import { mapState, mapActions } from "vuex";
import { localize } from "@nativescript/localize";
import * as utils from "~/shared/utils";
export default {
data() {
return {
toast: null,
};
},
computed: {
...mapState(["icon", "shakeEnabled"]),
items() {
return [
{},
{
type: "switch",
icon: "shuf",
title: "sVw",
subTitle: "sVwInfo",
checked: this.shakeEnabled,
action: this.toggleShake,
},
{},
];
},
},
methods: {
...mapActions(["setShake"]),
onPageLoad(args) {
const page = args.object;
page.bindingContext = new Observable();
},
// SHAKE VIEW RANDOM RECIPE
toggleShake({ object }) {
let checked = object.checked;
if (checked && !utils.hasAccelerometer()) {
object.checked = false;
this.toast = localize("noAccSensor");
utils.timer(5, (val) => {
if (!val) this.toast = val;
});
} else this.setShake(checked);
},
},
};
</script>

View file

@ -232,17 +232,7 @@
@tap="shareHandler"
/>
</GridLayout>
<GridLayout
v-show="toast"
row="1"
class="appbar snackBar"
columns="*"
@swipe="hideLastTried"
>
<FlexboxLayout minHeight="48" alignItems="center">
<Label class="title msg" :text="toast" />
</FlexboxLayout>
</GridLayout>
<Toast :toast="toast" :action="hideLastTried" />
<AbsoluteLayout rowSpan="2">
<Image
@tap="({ object }) => (object.cancel = true)"
@ -269,17 +259,18 @@ import {
Observable,
Screen,
CoreTypes,
Color,
} from "@nativescript/core";
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";
import ActionDialog from "./modal/ActionDialog.vue";
import PromptDialog from "./modal/PromptDialog.vue";
import Action from "./modals/Action.vue";
import Toast from "./sub/Toast.vue";
import Prompt from "./modals/Prompt.vue";
import * as utils from "~/shared/utils";
export default {
components: { Toast },
props: ["filterTrylater", "recipeID"],
data() {
return {
@ -337,9 +328,8 @@ export default {
"setRatingAction",
"toggleCartAction",
]),
onPageLoad(args) {
const page = args.object;
page.bindingContext = new Observable();
onPageLoad({ object }) {
object.bindingContext = new Observable();
this.busy = this.photoOpen = false;
this.setComponent("ViewRecipe");
if (this.yieldMultiplier == this.recipe.yieldQuantity)
@ -462,7 +452,7 @@ export default {
return localize(title) + text;
},
changeYield() {
this.$showModal(PromptDialog, {
this.$showModal(Prompt, {
props: {
title: `${localize("req", localize(this.recipe.yieldUnit))}`,
placeholder: Math.abs(parseFloat(this.yieldMultiplier)),
@ -694,7 +684,7 @@ export default {
// SHARE ACTION
shareHandler() {
if (this.recipe.image) {
this.$showModal(ActionDialog, {
this.$showModal(Action, {
props: {
title: "shr",
list: ["rec", "pht"],

View file

@ -50,7 +50,7 @@
import { Screen } from "@nativescript/core";
import { localize } from "@nativescript/localize";
import { mapState, mapActions } from "vuex";
import ConfirmDialog from "./ConfirmDialog.vue";
import Confirm from "./Confirm.vue";
interface IData {
newList: unknown[];
@ -92,7 +92,7 @@ export default {
this.$modal.close(item);
},
deletionConfirmation(description: string): void {
return this.$showModal(ConfirmDialog, {
return this.$showModal(Confirm, {
props: {
title: "conf",
description,

View file

@ -12,11 +12,7 @@
</v-template>
<v-template if="$index == 1">
<StackLayout class="app-info">
<Image
class="icon"
src="res://logo"
stretch="none"
/>
<Image class="icon" src="res://logo" stretch="none" />
<Label class="name tb tac" :text="'EnRecipes' | L" />
<Label :text="getVersion" class="version tb tac" />
@ -99,9 +95,8 @@ export default {
},
},
methods: {
onPageLoad(args) {
const page = args.object;
page.bindingContext = new Observable();
onPageLoad({ object }) {
object.bindingContext = new Observable();
},
// HELPERS
openURL(url) {

View file

@ -0,0 +1,82 @@
<template>
<Page @loaded="onPageLoad" actionBarHidden="true">
<GridLayout rows="*, auto" columns="auto, *">
<OptionsList title="Settings" :items="items" :action="navigateTo" />
<GridLayout row="1" class="appbar" rows="*" columns="auto, *">
<Button class="ico" :text="icon.back" @tap="$navigateBack()" />
</GridLayout>
</GridLayout>
</Page>
</template>
<script lang="ts">
import { Observable } from "@nativescript/core";
import { mapState, mapActions } from "vuex";
import Interface from "./Interface.vue";
import Options from "./Options.vue";
import Database from "./Database.vue";
import Reset from "./Reset.vue";
import About from "./About.vue";
import OptionsList from "../sub/OptionsList.vue";
export default {
components: { OptionsList },
data() {
return {
items: [
{},
{
type: "list",
icon: "interface",
title: "intf",
data: Interface,
},
{
type: "list",
icon: "opts",
title: "opts",
data: Options,
},
{
type: "list",
icon: "db",
title: "db",
data: Database,
},
{
type: "list",
icon: "reset",
title: "rest",
data: Reset,
},
{
type: "list",
icon: "info",
title: "About",
data: About,
},
{},
],
};
},
computed: {
...mapState(["icon"]),
},
methods: {
...mapActions(["setComponent"]),
onPageLoad({ object }) {
object.bindingContext = new Observable();
this.setComponent("Settings");
},
// HELPERS
navigateTo(view) {
this.$navigateTo(view, {
transition: {
name: "slide",
duration: 200,
curve: "easeOut",
},
});
},
},
};
</script>

View file

@ -0,0 +1,134 @@
<template>
<Page @loaded="onPageLoad" actionBarHidden="true">
<GridLayout rows="*, auto" columns="auto, *">
<OptionsList title="Settings" :items="items" />
<GridLayout row="1" class="appbar" rows="*" columns="auto, *">
<Button class="ico" :text="icon.back" @tap="$navigateBack()" />
</GridLayout>
</GridLayout>
</Page>
</template>
<script>
import { Observable, Device, Application, Utils } from "@nativescript/core";
import { mapState, mapActions } from "vuex";
import { localize } from "@nativescript/localize";
import OptionsList from "../sub/OptionsList";
import Action from "../modals/Action";
import * as utils from "~/shared/utils";
export default {
components: { OptionsList },
computed: {
...mapState(["icon", "timerDelay", "timerSound", "timerVibrate"]),
items() {
let options = [
{
type: "list",
icon: "sound",
title: "tmrSnd",
subTitle: this.timerSound.title,
action: this.showSoundsList,
},
{
type: "switch",
icon: "vibrate",
title: "tmrvbrt",
checked: this.timerVibrate,
action: this.toggleTimerVibrate,
},
];
let openSettings = [
{
type: "list",
icon: "sound",
title: "notifSetg",
subTitle: null,
action: this.openNotificationChannelSettings,
},
];
let list = this.channelExists() ? openSettings : options;
return [
{},
{
type: "list",
icon: "delay",
title: "dlyDur",
subTitle: this.timerDelay,
action: this.showDelayList,
},
...list,
{},
];
},
},
methods: {
...mapActions([
"setTimerDelay",
"setTimerSound",
"setTimerVibrate",
"setComponent",
]),
onPageLoad({ object }) {
object.bindingContext = new Observable();
this.setComponent("CTSettings");
},
showDelayList() {
let list = [
...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")}`
);
this.$showModal(Action, {
props: {
title: "dlyDur",
list,
},
}).then((dur) => dur && this.setTimerDelay(dur));
},
showSoundsList() {
let getTones = utils.getTones();
this.$showModal(Action, {
props: {
title: "tmrSnd",
list: getTones.tones.map((e) => e.title),
},
}).then(
(tone) =>
tone &&
tone !== this.timerSound.title &&
this.setTimerSound(getTones.tones.filter((e) => e.title === tone)[0])
);
},
toggleTimerVibrate() {
this.setTimerVibrate(!this.timerVibrate);
},
openNotificationChannelSettings() {
const ctx = Application.android.context;
const Settings = android.provider.Settings;
const Intent = android.content.Intent;
let intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
intent.putExtra(
Settings.EXTRA_APP_PACKAGE,
Application.android.packageName
);
intent.putExtra(Settings.EXTRA_CHANNEL_ID, "cta");
intent.setFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
ctx.startActivity(intent);
},
// HELPERS
channelExists() {
if (Device.sdkVersion * 1 >= 26) {
const ctx = Utils.ad.getApplicationContext();
const NotifySrv = ctx.getSystemService(
android.content.Context.NOTIFICATION_SERVICE
);
return NotifySrv.getNotificationChannel("cta");
}
return null;
},
},
};
</script>

View file

@ -1,32 +1,7 @@
<template>
<Page @loaded="onPageLoad" actionBarHidden="true">
<GridLayout rows="*, auto" columns="auto, *">
<ListView
colSpan="2"
rowSpan="2"
class="options-list"
for="item in items"
>
<v-template if="$index == 0">
<Label class="pageTitle" :text="'db' | L" />
</v-template>
<v-template if="$index == 4">
<StackLayout class="listSpace"> </StackLayout>
</v-template>
<v-template>
<GridLayout
columns="auto, *"
class="option"
@touch="touch($event, 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" class="sub" />
</StackLayout>
</GridLayout>
</v-template>
</ListView>
<OptionsList title="db" :items="items" />
<GridLayout
v-show="!toast && !progress"
row="1"
@ -36,18 +11,7 @@
>
<Button class="ico" :text="icon.back" @tap="$navigateBack()" />
</GridLayout>
<GridLayout
v-show="toast"
row="1"
colSpan="2"
class="appbar snackBar"
columns="*"
@tap="toast = null"
>
<FlexboxLayout minHeight="48" alignItems="center">
<Label class="title msg" :text="toast" />
</FlexboxLayout>
</GridLayout>
<Toast :toast="toast" :action="hideToast" />
<GridLayout
v-show="progress"
row="1"
@ -75,12 +39,15 @@ import {
getFileAccess,
} from "@nativescript/core";
import { localize } from "@nativescript/localize";
import ConfirmDialog from "../modal/ConfirmDialog.vue";
import Confirm from "../modals/Confirm";
import OptionsList from "../sub/OptionsList";
import Toast from "../sub/Toast";
import { mapState, mapActions } from "vuex";
import { openOrCreate } from "@akylas/nativescript-sqlite";
import * as utils from "~/shared/utils";
export default {
components: { OptionsList, Toast },
data() {
return {
backupFolder: null,
@ -103,18 +70,21 @@ export default {
return [
{},
{
type: "list",
icon: "folder",
title: "buFol",
subTitle: this.backupFolder,
action: this.setBackupFolder,
},
{
type: "list",
icon: "exp",
title: "expBu",
subTitle: localize("buInfo"),
action: this.exportCheck,
},
{
type: "list",
icon: "imp",
title: "impBu",
subTitle: localize("impInfo"),
@ -134,9 +104,8 @@ export default {
"unlinkBrokenImages",
"clearImportSummary",
]),
onPageLoad(args) {
const page = args.object;
page.bindingContext = new Observable();
onPageLoad({ object }) {
object.bindingContext = new Observable();
const ContentResolver = Application.android.nativeApp.getContentResolver();
this.backupFolder = ApplicationSettings.getString("backupFolder");
if (
@ -227,7 +196,7 @@ export default {
this.progress = null;
this.releaseBackEvent();
let description = localize("buto", `"${filename}"`);
this.$showModal(ConfirmDialog, {
this.$showModal(Confirm, {
props: {
title: "expSuc",
description,
@ -240,6 +209,7 @@ export default {
openZipFile() {
utils.getBackupFile().then((uri) => {
if (uri) {
knownFolders.temp().clear();
let dest = knownFolders.temp().path;
utils.Zip.unzip(uri, dest)
.then((res) => res && this.validateZipContent(res, uri))
@ -346,7 +316,7 @@ export default {
this.progress = null;
this.releaseBackEvent();
knownFolders.temp().clear();
this.$showModal(ConfirmDialog, {
this.$showModal(Confirm, {
props: {
title: "impFail",
description,
@ -366,7 +336,7 @@ export default {
const db = openOrCreate(recipesDB);
// Import recipes
db.select(`SELECT * FROM recipes`).then((res) => {
db.select("SELECT * FROM recipes").then((res) => {
this.importRecipesFromDB(res);
});
@ -426,7 +396,7 @@ export default {
Folder.fromPath(destPath);
utils.Zip.unzip(uri, destPath).then((res) => {
if (res) {
// delete unzipped json files
// delete unzipped data files
Folder.fromPath(path.join(destPath, "EnRecipes"))
.getEntities()
.then((entities) => {
@ -444,13 +414,12 @@ export default {
showImportSummary() {
this.progress = null;
this.releaseBackEvent();
knownFolders.temp().clear();
let { found, imported, updated } = this.importSummary;
let exists = Math.abs(found - imported - updated) + updated;
let importedNote = `\n${localize("recI")} ${imported}`;
let existsNote = `\n${localize("recE")} ${exists}`;
let updatedNote = `\n${localize("recU")} ${updated}`;
this.$showModal(ConfirmDialog, {
this.$showModal(Confirm, {
props: {
title: "impSuc",
description: `${found} ${localize(
@ -479,9 +448,8 @@ export default {
},
// HELPERS
touch({ object, action }, method) {
object.className = action.match(/down|move/) ? "option fade" : "option";
if (action == "up") method();
hideToast() {
this.toast = null;
},
},
};

View file

@ -1,32 +1,7 @@
<template>
<Page @loaded="onPageLoad" actionBarHidden="true">
<GridLayout rows="*, auto" columns="auto, *">
<ListView
colSpan="2"
rowSpan="2"
class="options-list"
for="item in items"
>
<v-template if="$index == 0">
<Label class="pageTitle" :text="'intf' | L" />
</v-template>
<v-template if="$index == 4">
<StackLayout class="listSpace"> </StackLayout>
</v-template>
<v-template>
<GridLayout
columns="auto, *"
class="option"
@touch="touch($event, item.action)"
>
<Label class="ico" :text="icon[item.icon]" />
<StackLayout col="1">
<Label :text="item.title | L" class="info" />
<Label :text="item.subTitle" class="sub" />
</StackLayout>
</GridLayout>
</v-template>
</ListView>
<OptionsList title="intf" :items="items" />
<GridLayout row="1" class="appbar" rows="*" columns="auto, *">
<Button class="ico" :text="icon.back" @tap="$navigateBack()" />
</GridLayout>
@ -42,12 +17,14 @@ import {
Frame,
} from "@nativescript/core";
import { localize, overrideLocale } from "@nativescript/localize";
import ActionDialog from "../modal/ActionDialog.vue";
import ConfirmDialog from "../modal/ConfirmDialog.vue";
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";
export default {
components: { OptionsList },
data() {
return {
appLanguage: "English",
@ -59,12 +36,14 @@ export default {
return [
{},
{
type: "list",
icon: "lang",
title: "lang",
subTitle: this.appLanguage,
action: this.selectAppLanguage,
},
{
type: "list",
icon: "theme",
title: "Theme",
subTitle: localize(
@ -73,6 +52,7 @@ export default {
action: this.selectThemes,
},
{
type: "list",
icon: "layout",
title: "listVM",
subTitle: localize(this.layout),
@ -84,14 +64,13 @@ export default {
},
methods: {
...mapActions(["setTheme", "setLayout"]),
onPageLoad(args) {
const page = args.object;
page.bindingContext = new Observable();
onPageLoad({ object }) {
object.bindingContext = new Observable();
},
// LANGUAGE SELECTION
selectAppLanguage() {
let languages = this.language.map((e) => e.title);
this.$showModal(ActionDialog, {
this.$showModal(Action, {
props: {
title: "lang",
list: [...languages],
@ -102,7 +81,7 @@ export default {
let locale = this.language.filter((e) => e.title === action)[0]
.locale;
if (currentLocale !== locale) {
this.$showModal(ConfirmDialog, {
this.$showModal(Confirm, {
props: {
title: "appRst",
description: localize("nLangInfo"),
@ -123,7 +102,7 @@ export default {
},
// THEME SELECTION
selectThemes() {
this.$showModal(ActionDialog, {
this.$showModal(Action, {
props: {
title: "Theme",
list: ["Light", "Dark", "Black", "sysDef", "sysDefB"],
@ -142,7 +121,7 @@ export default {
},
// LAYOUT MODE
setLayoutMode() {
this.$showModal(ActionDialog, {
this.$showModal(Action, {
props: {
title: "listVM",
list: ["detailed", "grid", "photogrid", "simple", "minimal"],
@ -155,13 +134,8 @@ export default {
}
});
},
// HELPERS
touch({ object, action }, method) {
object.className = action.match(/down|move/) ? "option fade" : "option";
if (action == "up") method();
},
},
mounted() {
created() {
this.appLanguage = ApplicationSettings.getString(
"appLanguage",
localize("sysDef")

View file

@ -0,0 +1,45 @@
<template>
<Page @loaded="onPageLoad" actionBarHidden="true">
<GridLayout rows="*, auto" columns="auto, *">
<OptionsList title="Settings" :items="items" />
<GridLayout row="1" class="appbar" rows="*" columns="auto, *">
<Button class="ico" :text="icon.back" @tap="$navigateBack()" />
</GridLayout>
</GridLayout>
</Page>
</template>
<script>
import { Observable } from "@nativescript/core";
import { mapState, mapActions } from "vuex";
import OptionsList from "../sub/OptionsList";
export default {
components: { OptionsList },
computed: {
...mapState(["icon", "mondayFirst"]),
items() {
return [
{},
{
type: "switch",
icon: "week",
title: "swm",
checked: this.mondayFirst,
action: this.toggleFirstDay,
},
{},
];
},
},
methods: {
...mapActions(["setFirstDay"]),
onPageLoad({ object }) {
object.bindingContext = new Observable();
},
toggleFirstDay() {
this.setFirstDay(!this.mondayFirst);
},
},
};
</script>

View file

@ -0,0 +1,69 @@
<template>
<Page @loaded="onPageLoad" actionBarHidden="true">
<GridLayout rows="*, auto" columns="auto, *">
<OptionsList title="opts" :items="items" />
<GridLayout
v-show="!toast"
row="1"
class="appbar"
rows="*"
columns="auto, *"
>
<Button class="ico" :text="icon.back" @tap="$navigateBack()" />
</GridLayout>
<Toast :toast="toast" :action="(toast = null)" />
</GridLayout>
</Page>
</template>
<script>
import { Observable } from "@nativescript/core";
import { mapState, mapActions } from "vuex";
import { localize } from "@nativescript/localize";
import OptionsList from "../sub/OptionsList";
import Toast from "../sub/Toast";
import * as utils from "~/shared/utils";
export default {
components: { OptionsList, Toast },
data() {
return {
toast: null,
};
},
computed: {
...mapState(["icon", "shakeEnabled"]),
items() {
return [
{},
{
type: "switch",
icon: "shuf",
title: "sVw",
subTitle: "sVwInfo",
checked: this.shakeEnabled,
action: this.toggleShake,
},
{},
];
},
},
methods: {
...mapActions(["setShake"]),
onPageLoad({ object }) {
object.bindingContext = new Observable();
},
// 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);
},
},
};
</script>

View file

@ -1,34 +1,9 @@
<template>
<Page @loaded="onPageLoad" actionBarHidden="true">
<GridLayout rows="*, auto" columns="auto, *">
<ListView
colSpan="2"
rowSpan="2"
class="options-list"
for="item in items"
>
<v-template if="$index == 0">
<Label class="pageTitle" :text="'rest' | L" />
</v-template>
<v-template if="$index == 5">
<Label class="group-info sub tw" :text="'restInfo' | L" />
</v-template>
<v-template if="$index == 6">
<StackLayout class="listSpace"> </StackLayout>
</v-template>
<v-template>
<GridLayout
columns="auto, *"
class="option"
@touch="touch($event, item.type)"
>
<Label class="ico" :text="icon.reset" />
<Label col="1" :text="item.title | L" class="info" />
</GridLayout>
</v-template>
</ListView>
<OptionsList title="rest" :items="items" :action="resetListItems" />
<GridLayout
v-show="!toast"
:hidden="toast"
row="1"
class="appbar"
@loaded="onAppBarLoad"
@ -36,18 +11,7 @@
>
<Button class="ico" :text="icon.back" @tap="$navigateBack()" />
</GridLayout>
<GridLayout
v-show="toast"
row="1"
colSpan="2"
class="appbar snackBar"
columns="*"
@swipe="hideToast"
>
<FlexboxLayout minHeight="48" alignItems="center">
<Label class="title msg" :text="toast" />
</FlexboxLayout>
</GridLayout>
<Toast :toast="toast" :action="hideToast" />
</GridLayout>
</Page>
</template>
@ -57,7 +21,10 @@ import { Observable, CoreTypes } 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";
export default {
components: { OptionsList, Toast },
data() {
return {
toast: null,
@ -70,20 +37,28 @@ export default {
return [
{},
{
type: "cuisines",
type: "list",
icon: "reset",
title: "restCuiL",
data: "cuisines",
},
{
type: "categories",
type: "list",
icon: "reset",
title: "restCatL",
data: "categories",
},
{
type: "yieldUnits",
type: "list",
icon: "reset",
title: "restYUL",
data: "yieldUnits",
},
{
type: "units",
type: "list",
icon: "reset",
title: "restUL",
data: "units",
},
{},
{},
@ -92,9 +67,8 @@ export default {
},
methods: {
...mapActions(["resetListItemsAction"]),
onPageLoad(args) {
const page = args.object;
page.bindingContext = new Observable();
onPageLoad({ object }) {
object.bindingContext = new Observable();
},
onAppBarLoad({ object }) {
this.appbar = object;
@ -111,6 +85,7 @@ export default {
});
},
hideToast({ object }) {
this.appbar.translateY = 64;
object
.animate({
opacity: 0,
@ -120,7 +95,7 @@ export default {
})
.then(() => {
this.showUndo = false;
this.appbar.translateY = 64;
this.toast = null;
this.appbar.animate({
translate: { x: 0, y: 0 },
duration: 250,
@ -128,13 +103,8 @@ export default {
});
object.opacity = 1;
object.translateY = 0;
this.toast = null;
});
},
touch({ object, action }, type) {
object.className = action.match(/down|move/) ? "option fade" : "option";
if (action == "up") this.resetListItems(type);
},
},
};
</script>

View file

@ -0,0 +1,62 @@
<template>
<ListView colSpan="2" rowSpan="2" class="options-list" for="item in items">
<v-template if="$index == 0">
<Label class="pageTitle" :text="title | L" />
</v-template>
<v-template if="item.type == 'switch'">
<GridLayout
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" />
</StackLayout>
<Switch
isUserInteractionEnabled="false"
:color="item.checked ? '#ff5200' : '#adb5bd'"
col="2"
:checked="item.checked"
/>
</GridLayout>
</v-template>
<v-template if="item.type == 'list'">
<GridLayout
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" />
</StackLayout>
</GridLayout>
</v-template>
<v-template if="item.type == 'info'">
<Label class="group-info sub tw" :text="item.title | L" />
</v-template>
<v-template>
<StackLayout class="listSpace"> </StackLayout>
</v-template>
</ListView>
</template>
<script>
import { mapState } from "vuex";
export default {
props: ["title", "items", "action"],
computed: {
...mapState(["icon"]),
},
methods: {
touch({ object, action }, data, localAction) {
object.className = action.match(/down|move/) ? "option fade" : "option";
if (action == "up") localAction ? localAction(data) : this.action(data);
},
},
};
</script>

View file

@ -0,0 +1,23 @@
<template>
<GridLayout
row="1"
class="appbar snackBar"
columns="auto, *, auto"
@swipe="action"
>
<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>
</template>
<script>
import { mapState } from "vuex";
export default {
props: ["count", "msg", "undo", "action"],
computed: {
...mapState(["icon"]),
},
};
</script>

View file

@ -48,7 +48,7 @@
import { ApplicationSettings, Application } from "@nativescript/core";
import { localize } from "@nativescript/localize";
import { mapState, mapActions } from "vuex";
import ActionDialogWithSearch from "./modal/ActionDialogWithSearch.vue";
import ActionWithSearch from "../modals/ActionWithSearch";
import * as utils from "~/shared/utils";
import { EventBus } from "~/main";
@ -92,7 +92,7 @@ export default {
methods: {
...mapActions(["removeActiveTimer", "updateActiveTimer", "addTimerPreset"]),
attachRecipe() {
this.$showModal(ActionDialogWithSearch, {
this.$showModal(ActionWithSearch, {
props: {
title: "selRec",
recipes: this.recipes,
@ -140,7 +140,7 @@ export default {
},
clearNotification() {
Application.android.unregisterBroadcastReceiver("timer" + this.timer.id);
utils.TimerNotification.clear(this.timer.id);
utils.TimerNotif.clear(this.timer.id);
},
toggleProgress(bool) {
this.togglePause(this.timer, bool);

View file

@ -0,0 +1,20 @@
<template>
<GridLayout
v-show="toast"
row="1"
colSpan="2"
class="appbar snackBar"
columns="*"
@swipe="action"
>
<FlexboxLayout minHeight="48" alignItems="center">
<Label class="title msg" :text="toast" />
</FlexboxLayout>
</GridLayout>
</template>
<script>
export default {
props: ["toast", "action"],
};
</script>

View file

@ -309,5 +309,6 @@
"hour": "hour",
"hours": "hours",
"seconds": "seconds",
"tmrClr": "Timer cleared"
"tmrRm": "Timer removed",
"notifSetg": "Notification settings"
}

View file

@ -2,9 +2,27 @@ import {
localize,
androidLaunchEventLocalizationHandler,
} from '@nativescript/localize'
import { on, launchEvent } from '@nativescript/core/application'
import { Application, AndroidApplication, Utils } from '@nativescript/core'
on(launchEvent, ({ android }) => {
const keepScreenOn = () => {
let ctx = Utils.ad.getApplicationContext()
const pm = ctx.getSystemService(android.content.Context.POWER_SERVICE)
let isScreenOff = !pm.isInteractive()
if (isScreenOff) {
console.log('keepScreenOn')
const window = Application.android.startActivity.getWindow()
const windowMgr = android.view.WindowManager
window.addFlags(
windowMgr.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
windowMgr.LayoutParams.FLAG_TURN_SCREEN_ON |
windowMgr.LayoutParams.FLAG_KEEP_SCREEN_ON
)
}
}
Application.on(Application.resumeEvent, keepScreenOn)
Application.on(Application.launchEvent, ({ android }) => {
console.log('launching')
if (android) androidLaunchEventLocalizationHandler()
})
@ -17,7 +35,7 @@ export const EventBus = new Vue()
import CollectionView from '@nativescript-community/ui-collectionview/vue'
Vue.use(CollectionView)
import { lvMixin } from './shared/mixins.js'
import { lvMixin } from './shared/mixins'
Vue.mixin(lvMixin)
Vue.config.silent = false

View file

@ -1,17 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="__PACKAGE__" android:versionCode="10000" android:versionName="1.0">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.CAMERA" tools:node="remove" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" tools:node="remove" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:node="remove" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" tools:node="remove" />
<uses-permission android:name="android.permission.INTERNET" tools:node="remove" />
<uses-permission android:name="android.permission.RECORD_AUDIO" tools:node="remove" />
<application android:extractNativeLibs="true" android:name="com.tns.NativeScriptApplication" android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:hardwareAccelerated="true" android:largeHeap="true" android:theme="@style/AppTheme">
<activity android:name="com.tns.NativeScriptActivity" android:label="@string/title_activity_kimera" android:launchMode="singleTop" android:screenOrientation="userPortrait" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout|locale|uiMode" android:theme="@style/LaunchScreenTheme" android:windowSoftInputMode="adjustResize">
<activity android:name="com.tns.NativeScriptActivity" android:label="@string/title_activity_kimera" android:launchMode="singleInstance" android:screenOrientation="userPortrait" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout|locale|uiMode" android:theme="@style/LaunchScreenTheme" android:windowSoftInputMode="adjustResize">
<meta-data android:name="SET_THEME_ON_LAUNCH" android:resource="@style/AppTheme" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@ -19,6 +20,7 @@
</intent-filter>
</activity>
<activity android:name="com.tns.ErrorReportActivity" />
<service android:name="com.tns.ForegroundService" android:enabled="true" android:exported="false" />
<provider android:name="androidx.core.content.FileProvider" android:exported="false" android:authorities="${applicationId}.provider" android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider" />
</provider>

View file

@ -313,4 +313,6 @@
<string name="aBtn">"أضف"</string>
<string name="About">"حول"</string>
<string name="aap">"ألحق صورة"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
</resources>

View file

@ -90,7 +90,8 @@
<string name="allTs">"Totes les etiquetes"</string>
<string name="allCats">"Totes les categories"</string>
<string name="About">"Quant a"</string>
<string name="tmrClr">"Timer cleared"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
<string name="seconds">"seconds"</string>
<string name="hours">"hours"</string>
<string name="hour">"hour"</string>
@ -313,4 +314,5 @@
<string name="aD">"All done!"</string>
<string name="aBtn">"ADD"</string>
<string name="aap">"Attach a photo"</string>
<string name="tmrClr">"tmrClr"</string>
</resources>

View file

@ -313,4 +313,6 @@
<string name="American">"American"</string>
<string name="aD">"Fuldendt!"</string>
<string name="About">"Om"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
</resources>

View file

@ -313,4 +313,6 @@
<string name="aBtn">"HINZUFÜGEN"</string>
<string name="About">"Über"</string>
<string name="aap">"Foto anhängen"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
</resources>

View file

@ -313,4 +313,6 @@
<string name="aBtn">"ADD"</string>
<string name="About">"About"</string>
<string name="aap">"Attach a photo"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
</resources>

View file

@ -313,4 +313,6 @@
<string name="aBtn">"ADD"</string>
<string name="About">"About"</string>
<string name="aap">"Attach a photo"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
</resources>

View file

@ -20,7 +20,8 @@
<string name="aStpBtn">"AGREGAR PASO"</string>
<string name="August">"Agosto"</string>
<string name="sec">"s"</string>
<string name="tmrClr">"Timer cleared"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
<string name="seconds">"seconds"</string>
<string name="hours">"hours"</string>
<string name="hour">"hour"</string>
@ -313,4 +314,5 @@
<string name="title_activity_kimera">"EnRecipes"</string>
<string name="allTs">"All Tags"</string>
<string name="allCuis">"All Cuisines"</string>
<string name="tmrClr">"tmrClr"</string>
</resources>

View file

@ -313,4 +313,6 @@
<string name="aBtn">"AÑADIR"</string>
<string name="About">"Acerca de"</string>
<string name="aap">"Adjuntar una foto"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
</resources>

View file

@ -309,8 +309,10 @@
<string name="aBtn">"LISÄÄ"</string>
<string name="About">"Tietoja"</string>
<string name="aap">"Liitä valokuva"</string>
<string name="tmrClr">"Timer cleared"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
<string name="tmrvbrt">"Timer vibrate"</string>
<string name="delay">"Delay"</string>
<string name="strtBtn">"START"</string>
<string name="tmrClr">"tmrClr"</string>
</resources>

View file

@ -313,4 +313,6 @@
<string name="aBtn">"AJOUTER"</string>
<string name="About">"À propos"</string>
<string name="aap">"Joindre une photo"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
</resources>

View file

@ -313,4 +313,6 @@
<string name="aBtn">"AJOUTER"</string>
<string name="About">"À propos"</string>
<string name="aap">"Joindre une photo"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
</resources>

View file

@ -313,4 +313,6 @@
<string name="aBtn">"AJOUTER"</string>
<string name="About">"À propos"</string>
<string name="aap">"Joindre une photo"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
</resources>

View file

@ -313,4 +313,6 @@
<string name="aBtn">"AJOUTER"</string>
<string name="About">"À propos"</string>
<string name="aap">"Joindre une photo"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
</resources>

View file

@ -313,4 +313,6 @@
<string name="aBtn">"जोड़ें"</string>
<string name="About">"तकरीबन"</string>
<string name="aap">"एक तस्वीर लगाओ"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
</resources>

View file

@ -313,4 +313,6 @@
<string name="aBtn">"Tambah"</string>
<string name="About">"Tentang"</string>
<string name="aap">"Lampirkan foto"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
</resources>

View file

@ -313,4 +313,6 @@
<string name="aBtn">"AGGIUNGI"</string>
<string name="About">"Informazioni"</string>
<string name="aap">"Allega una foto"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
</resources>

View file

@ -289,7 +289,8 @@
<string name="aBtn">"追加"</string>
<string name="About">"アプリについて"</string>
<string name="aap">"写真を添付"</string>
<string name="tmrClr">"Timer cleared"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
<string name="seconds">"seconds"</string>
<string name="hours">"hours"</string>
<string name="hour">"hour"</string>
@ -313,4 +314,5 @@
<string name="_app_name_1k3Sbz">"EnRecipes"</string>
<string name="app_name">"EnRecipes"</string>
<string name="title_activity_kimera">"EnRecipes"</string>
<string name="tmrClr">"tmrClr"</string>
</resources>

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="tmrClr">"Timer cleared"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
<string name="seconds">"seconds"</string>
<string name="hours">"hours"</string>
<string name="hour">"hour"</string>
@ -313,4 +314,5 @@
<string name="aBtn">"ADD"</string>
<string name="About">"About"</string>
<string name="aap">"Attach a photo"</string>
<string name="tmrClr">"tmrClr"</string>
</resources>

View file

@ -293,7 +293,8 @@
<string name="aBtn">"ചേർക്കുക"</string>
<string name="About">"കുറിച്ച്"</string>
<string name="aap">"ഒരു ഫോട്ടോ അറ്റാച്ചുചെയ്യുക"</string>
<string name="tmrClr">"Timer cleared"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
<string name="seconds">"seconds"</string>
<string name="hours">"hours"</string>
<string name="hour">"hour"</string>
@ -313,4 +314,5 @@
<string name="ntmr">"New timer"</string>
<string name="timer">"Cooking Timer"</string>
<string name="sec">"sec"</string>
<string name="tmrClr">"tmrClr"</string>
</resources>

View file

@ -294,7 +294,8 @@
<string name="aBtn">"Legg til"</string>
<string name="About">"Om"</string>
<string name="aap">"Legg ved et bilde"</string>
<string name="tmrClr">"Timer cleared"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
<string name="seconds">"seconds"</string>
<string name="hours">"hours"</string>
<string name="hour">"hour"</string>
@ -313,4 +314,5 @@
<string name="strtBtn">"START"</string>
<string name="ntmr">"New timer"</string>
<string name="timer">"Cooking Timer"</string>
<string name="tmrClr">"tmrClr"</string>
</resources>

View file

@ -313,4 +313,6 @@
<string name="aBtn">"TOEVOEGEN"</string>
<string name="About">"Over"</string>
<string name="aap">"Foto bijvoegen"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
</resources>

View file

@ -313,4 +313,6 @@
<string name="aD">"Tudo feito!"</string>
<string name="aBtn">"ADICIONAR"</string>
<string name="About">"Sobre"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
</resources>

View file

@ -313,4 +313,6 @@
<string name="American">"Americana"</string>
<string name="About">"Sobre"</string>
<string name="aap">"Anexar uma fotografia"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
</resources>

View file

@ -313,4 +313,6 @@
<string name="aBtn">"ДОБАВИТЬ"</string>
<string name="About">"О приложении"</string>
<string name="aap">"Прикрепить фото"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
</resources>

View file

@ -293,7 +293,8 @@
<string name="aBtn">"சேர்"</string>
<string name="About">"பற்றி"</string>
<string name="aap">"புகைப்படத்தை இணைக்கவும்"</string>
<string name="tmrClr">"Timer cleared"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
<string name="seconds">"seconds"</string>
<string name="hours">"hours"</string>
<string name="hour">"hour"</string>
@ -313,4 +314,5 @@
<string name="ntmr">"New timer"</string>
<string name="timer">"Cooking Timer"</string>
<string name="sec">"sec"</string>
<string name="tmrClr">"tmrClr"</string>
</resources>

View file

@ -293,7 +293,8 @@
<string name="aBtn">"చేర్చు"</string>
<string name="About">"గురించి"</string>
<string name="aap">"ఫోటోను అటాచ్ చేయండి"</string>
<string name="tmrClr">"Timer cleared"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
<string name="seconds">"seconds"</string>
<string name="hours">"hours"</string>
<string name="hour">"hour"</string>
@ -313,4 +314,5 @@
<string name="ntmr">"New timer"</string>
<string name="timer">"Cooking Timer"</string>
<string name="sec">"sec"</string>
<string name="tmrClr">"tmrClr"</string>
</resources>

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="tmrClr">"Timer cleared"</string>
<string name="notifSetg">"Notification settings"</string>
<string name="tmrRm">"Timer removed"</string>
<string name="seconds">"seconds"</string>
<string name="hours">"hours"</string>
<string name="hour">"hour"</string>
@ -313,4 +314,5 @@
<string name="aBtn">"ADD"</string>
<string name="About">"About"</string>
<string name="aap">"Attach a photo"</string>
<string name="tmrClr">"tmrClr"</string>
</resources>

View file

@ -1,3 +1,5 @@
declare const android: any
export const lvMixin = {
methods: {
transparentPage({ object }) {

View file

@ -8,6 +8,8 @@ import {
knownFolders,
} from '@nativescript/core'
let timerOne
declare const global, android, androidx, com, java, Array: any
export const restartApp = () => {
const ctx = Utils.ad.getApplicationContext()
let mStartActivity = new android.content.Intent(
@ -93,11 +95,12 @@ export const getRecipePhoto = () => {
android.content.Intent.ACTION_GET_CONTENT
)
intent.setType('image/*')
return callIntent(ctx, intent, 'Select photo', DIR_CODE).then((res) => {
if (res.resultCode === android.app.Activity.RESULT_OK)
if (res.intent != null && res.intent.getData())
return res.intent.getData()
})
return callIntent(ctx, intent, 'Select photo', DIR_CODE).then(
({ resultCode, intent }: any) => {
if (resultCode === android.app.Activity.RESULT_OK)
if (intent != null && intent.getData()) return intent.getData()
}
)
}
export const copyPhotoToCache = (uri, filepath) => {
const ContentResolver = Application.android.nativeApp.getContentResolver()
@ -129,7 +132,7 @@ export const copyDBToExport = () => {
const input = new java.io.FileInputStream(src)
try {
const output = new java.io.FileOutputStream(dst)
let len
let len: number
let buffer = Array.create('byte', 1024)
while ((len = input.read(buffer)) > 0) output.write(buffer, 0, len)
} catch (error) {
@ -147,11 +150,12 @@ export const getBackupFolder = () => {
const intent = new android.content.Intent(
android.content.Intent.ACTION_OPEN_DOCUMENT_TREE
)
return callIntent(ctx, intent, 'Select folder', DIR_CODE).then((res) => {
if (res.resultCode === android.app.Activity.RESULT_OK)
if (res.intent != null && res.intent.getData())
return res.intent.getData()
})
return callIntent(ctx, intent, 'Select folder', DIR_CODE).then(
({ resultCode, intent }: any) => {
if (resultCode === android.app.Activity.RESULT_OK)
if (intent != null && intent.getData()) return intent.getData()
}
)
}
// BACKUP FILE PICKER
@ -165,10 +169,9 @@ export const getBackupFile = () => {
intent.addCategory(android.content.Intent.CATEGORY_OPENABLE)
intent.setType('application/zip')
return callIntent(ctx, intent, 'Select file to import', DIR_CODE).then(
(res) => {
if (res.resultCode === android.app.Activity.RESULT_OK) {
if (res.intent != null && res.intent.getData())
return res.intent.getData()
({ resultCode, intent }: any) => {
if (resultCode === android.app.Activity.RESULT_OK) {
if (intent != null && intent.getData()) return intent.getData()
}
}
)
@ -176,7 +179,7 @@ export const getBackupFile = () => {
// ZIP OPERATIONS
export class Zip {
static getSubFiles(src, isRootFolder) {
static getSubFiles(src: string, isRootFolder?: boolean) {
const fileList = new java.util.ArrayList()
const sourceFile = new java.io.File(src)
let tempList = sourceFile.listFiles()
@ -301,8 +304,8 @@ export const shareImage = (image, subject) => {
}
// TIMER NOTIFICATION
export class TimerNotification {
static getResource(ctx, icon) {
export class TimerNotif {
static getIcon(ctx, icon) {
const packageName = ctx.getApplicationInfo().packageName
let resources = ctx.getResources()
return (
@ -328,36 +331,33 @@ export class TimerNotification {
sound,
title,
vibrate,
}: {
actions?: boolean
bID: string
cID: string
cName: string
description: string
nID: number
priority: number
sound: string
title: string
vibrate?: number
}) {
let sdkv = Device.sdkVersion * 1
let soundUri
let sdkv: number = parseInt(Device.sdkVersion)
let soundUri: any
if (sound) soundUri = new android.net.Uri.parse(sound)
const NotifyMgr = android.app.NotificationManager
let ctx = Utils.ad.getApplicationContext()
const NotifySrv = ctx.getSystemService(
android.content.Context.NOTIFICATION_SERVICE
)
if (priority) {
// Show over lock screen
Application.android.on(AndroidApplication.activityResumedEvent, () => {
const window = Application.android.startActivity.getWindow()
const windowMgr = android.view.WindowManager
window.addFlags(
windowMgr.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
windowMgr.LayoutParams.FLAG_TURN_SCREEN_ON |
windowMgr.LayoutParams.FLAG_KEEP_SCREEN_ON
)
})
}
if (sdkv >= 26) {
const importance = priority
? NotifyMgr.IMPORTANCE_HIGH
: NotifyMgr.IMPORTANCE_DEFAULT
const importance =
priority > 0 ? NotifyMgr.IMPORTANCE_HIGH : NotifyMgr.IMPORTANCE_MIN
console.log(priority, importance)
const AudioAttributes = android.media.AudioAttributes
const audioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ALARM)
.build()
const Channel = new android.app.NotificationChannel(
@ -409,7 +409,8 @@ export class TimerNotification {
// CREATE NOTIFICATION
const NotificationCompat = androidx.core.app.NotificationCompat
let icon = TimerNotification.getResource(ctx, 'ic_stat_notify_silhouette')
const AudioManager = android.media.AudioManager
let icon = TimerNotif.getIcon(ctx, 'ic_stat_notify_silhouette')
let builder = new NotificationCompat.Builder(ctx, cID)
.setColor(new Color('#ff5200').android)
.setContentIntent(mainPInt)
@ -418,9 +419,10 @@ export class TimerNotification {
.setPriority(priority)
.setShowWhen(actions)
.setSmallIcon(icon)
.setSound(sound ? soundUri : null)
.setTicker(title)
.setAutoCancel(false)
if (sound) builder.setSound(soundUri, AudioManager.STREAM_ALARM)
else builder.setSound(null)
if (description) builder.setContentText(description)
if (vibrate) builder.setVibrate([500, 1000])
if (actions) {
@ -430,19 +432,20 @@ export class TimerNotification {
builder.addAction(null, 'Stop', actionPInt2)
}
let notification = builder.build()
notification.flags = NotificationCompat.FLAG_INSISTENT
notification.flags =
NotificationCompat.FLAG_INSISTENT | NotificationCompat.FLAG_ONGOING_EVENT
NotifySrv.notify(nID, notification)
}
}
// GET RINGTONES LIST
export const getTones = () => {
let ctx = Utils.ad.getApplicationContext()
let tones = []
const RingtoneManager = android.media.RingtoneManager
let ctx = Utils.ad.getApplicationContext()
const ringtonesMgr = new RingtoneManager(ctx)
ringtonesMgr.setType(RingtoneManager.TYPE_ALARM)
const cursor = ringtonesMgr.getCursor()
let tones = []
while (cursor.moveToNext()) {
tones.push({
title: cursor.getString(RingtoneManager.TITLE_COLUMN_INDEX),
@ -452,5 +455,21 @@ export const getTones = () => {
cursor.getString(RingtoneManager.ID_COLUMN_INDEX),
})
}
return tones
let defaultToneUri = RingtoneManager.getActualDefaultRingtoneUri(
ctx,
RingtoneManager.TYPE_ALARM
)
let defaultTone
if (defaultToneUri) {
let uriString = defaultToneUri.toString()
let tonesAvailable = tones.filter((e) => e.uri == uriString)
let toneExist = tonesAvailable.length
defaultTone = {
title: toneExist ? tonesAvailable[0].title : tones[0].title,
uri: toneExist ? uriString : tones[0].uri,
}
}
return { tones, defaultTone: defaultToneUri ? defaultTone : tones[0] }
}

View file

@ -387,8 +387,7 @@ export default new Vuex.Store({
title: sound.title,
uri: sound.uri,
}
ApplicationSettings.setString('timerSoundTitle', sound.title)
ApplicationSettings.setString('timerSoundUri', sound.uri)
ApplicationSettings.setString('timerSound', JSON.stringify(sound))
},
setTimerVibrate(state, bool) {
state.timerVibrate = bool
@ -626,9 +625,7 @@ export default new Vuex.Store({
)
if (partition[0].length) createDocuments(partition[0])
if (partition[1].length) updateDocuments(partition[1])
} else {
createDocuments(recipes)
}
} else createDocuments(recipes)
state.importSummary.found = recipes.length
state.importSummary.imported = imported
state.importSummary.updated = updated

2253
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -6,7 +6,7 @@
"lib": ["dom", "es2017"],
"sourceMap": true,
"noEmitHelpers": true,
"importHelpers": true,
"importHelpers": false, // Must be false to create custom android componentt
"baseUrl": ".",
"paths": {
"~/*": ["app/*"],

View file

@ -1,6 +1,20 @@
const webpack = require('@nativescript/webpack')
const path = require('path')
module.exports = (env) => {
webpack.init(env)
const platform = webpack.Utils.platform.getPlatformName()
webpack.chainWebpack((config) => {
if (platform === 'android') {
const appComponents = [
'@nativescript/core/ui/frame',
'@nativescript/core/ui/frame/activity',
path.resolve(__dirname, 'app/ForegroundService.js'),
]
appComponents.map((component) => {
config.entry('bundle').add(component)
})
}
})
return webpack.resolveConfig()
}