optimized recipe editing
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
android {
|
android {
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
|
versionCode 1
|
||||||
|
versionName '1.0.0'
|
||||||
minSdkVersion 25
|
minSdkVersion 25
|
||||||
generatedDensities = []
|
generatedDensities = []
|
||||||
ndk {
|
ndk {
|
|
@ -7,8 +7,8 @@
|
||||||
<!-- <uses-permission android:name="android.permission.READ_USER_DICTIONARY" /> -->
|
<!-- <uses-permission android:name="android.permission.READ_USER_DICTIONARY" /> -->
|
||||||
<!-- <uses-permission android:name="android.permission.INTERNET"/> -->
|
<!-- <uses-permission android:name="android.permission.INTERNET"/> -->
|
||||||
<!-- <uses-feature android:name="android.hardware.camera" android:required="true" /> -->
|
<!-- <uses-feature android:name="android.hardware.camera" android:required="true" /> -->
|
||||||
<application android:usesCleartextTraffic="true" android:name="com.tns.NativeScriptApplication" android:allowBackup="true" android:icon="@drawable/icon" android:label="@string/app_name" android:theme="@style/AppTheme" android:requestLegacyExternalStorage="true">
|
<application android:name="com.tns.NativeScriptApplication" android:allowBackup="true" android:icon="@drawable/icon" android:label="@string/app_name" android:theme="@style/AppTheme" android:requestLegacyExternalStorage="true">
|
||||||
<activity android:name="com.tns.NativeScriptActivity" android:label="@string/title_activity_kimera" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout|locale|uiMode" android:theme="@style/LaunchScreenTheme">
|
<activity android:name="com.tns.NativeScriptActivity" android:label="@string/title_activity_kimera" android:screenOrientation="portrait" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout|locale|uiMode" android:theme="@style/LaunchScreenTheme" android:windowSoftInputMode="adjustPan">
|
||||||
<meta-data android:name="SET_THEME_ON_LAUNCH" android:resource="@style/AppTheme" />
|
<meta-data android:name="SET_THEME_ON_LAUNCH" android:resource="@style/AppTheme" />
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
Before Width: | Height: | Size: 550 B After Width: | Height: | Size: 550 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.8 KiB |
Before Width: | Height: | Size: 461 B After Width: | Height: | Size: 461 B |
Before Width: | Height: | Size: 664 B After Width: | Height: | Size: 664 B |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 472 B After Width: | Height: | Size: 472 B |
Before Width: | Height: | Size: 780 B After Width: | Height: | Size: 780 B |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 680 B After Width: | Height: | Size: 680 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 861 B After Width: | Height: | Size: 861 B |
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
<!-- Application theme -->
|
<!-- Application theme -->
|
||||||
<style name="AppThemeBase29" parent="AppThemeBase21">
|
<style name="AppThemeBase29" parent="AppThemeBase21">
|
||||||
<item name="android:forceDarkAllowed">true</item>
|
<item name="android:forceDarkAllowed">false</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="AppTheme" parent="AppThemeBase29">
|
<style name="AppTheme" parent="AppThemeBase29">
|
60
App_Resources/Android/src/main/res/values/styles.xml
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<!-- theme to use FOR launch screen -->
|
||||||
|
<style name="LaunchScreenThemeBase" parent="Theme.AppCompat.Light.NoActionBar">
|
||||||
|
<item name="toolbarStyle">
|
||||||
|
@style/NativeScriptToolbarStyle
|
||||||
|
</item>
|
||||||
|
<item name="colorPrimary">
|
||||||
|
@color/ns_primary
|
||||||
|
</item>
|
||||||
|
<item name="colorPrimaryDark">
|
||||||
|
@color/ns_primaryDark
|
||||||
|
</item>
|
||||||
|
<item name="colorAccent">
|
||||||
|
@color/ns_accent
|
||||||
|
</item>
|
||||||
|
<item name="android:windowBackground">
|
||||||
|
@drawable/splash_screen
|
||||||
|
</item>
|
||||||
|
<item name="android:windowActionBarOverlay">
|
||||||
|
true
|
||||||
|
</item>
|
||||||
|
<item name="android:windowTranslucentStatus">
|
||||||
|
true
|
||||||
|
</item>
|
||||||
|
</style>
|
||||||
|
<style name="LaunchScreenTheme" parent="LaunchScreenThemeBase">
|
||||||
|
</style>
|
||||||
|
<!-- theme to use AFTER launch screen is loaded -->
|
||||||
|
<style name="AppThemeBase" parent="Theme.AppCompat.Light.NoActionBar">
|
||||||
|
<item name="toolbarStyle">
|
||||||
|
@style/NativeScriptToolbarStyle
|
||||||
|
</item>
|
||||||
|
<item name="colorPrimary">
|
||||||
|
@color/ns_primary
|
||||||
|
</item>
|
||||||
|
<item name="colorPrimaryDark">
|
||||||
|
@color/ns_primaryDark
|
||||||
|
</item>
|
||||||
|
<item name="colorAccent">
|
||||||
|
@color/ns_accent
|
||||||
|
</item>
|
||||||
|
</style>
|
||||||
|
<style name="AppTheme" parent="AppThemeBase">
|
||||||
|
</style>
|
||||||
|
<!-- theme for action-bar -->
|
||||||
|
<style name="NativeScriptToolbarStyleBase" parent="Widget.AppCompat.Toolbar">
|
||||||
|
<item name="android:background">
|
||||||
|
@color/ns_primary
|
||||||
|
</item>
|
||||||
|
<item name="theme">
|
||||||
|
@style/ThemeOverlay.AppCompat.ActionBar
|
||||||
|
</item>
|
||||||
|
<item name="popupTheme">
|
||||||
|
@style/ThemeOverlay.AppCompat
|
||||||
|
</item>
|
||||||
|
</style>
|
||||||
|
<style name="NativeScriptToolbarStyle" parent="NativeScriptToolbarStyleBase">
|
||||||
|
</style>
|
||||||
|
</resources>
|
|
@ -1,41 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
<!-- theme to use FOR launch screen-->
|
|
||||||
<style name="LaunchScreenThemeBase" parent="Theme.AppCompat.Light.NoActionBar">
|
|
||||||
<item name="toolbarStyle">@style/NativeScriptToolbarStyle</item>
|
|
||||||
|
|
||||||
<item name="colorPrimary">@color/ns_primary</item>
|
|
||||||
<item name="colorPrimaryDark">@color/ns_primaryDark</item>
|
|
||||||
<item name="colorAccent">@color/ns_accent</item>
|
|
||||||
|
|
||||||
<item name="android:windowBackground">@drawable/splash_screen</item>
|
|
||||||
|
|
||||||
<item name="android:windowActionBarOverlay">true</item>
|
|
||||||
<item name="android:windowTranslucentStatus">false</item>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style name="LaunchScreenTheme" parent="LaunchScreenThemeBase">
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<!-- theme to use AFTER launch screen is loaded-->
|
|
||||||
<style name="AppThemeBase" parent="Theme.AppCompat.Light.NoActionBar">
|
|
||||||
<item name="toolbarStyle">@style/NativeScriptToolbarStyle</item>
|
|
||||||
<item name="colorPrimary">@color/ns_primary</item>
|
|
||||||
<item name="colorPrimaryDark">@color/ns_primaryDark</item>
|
|
||||||
<item name="colorAccent">@color/ns_accent</item>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style name="AppTheme" parent="AppThemeBase">
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<!-- theme for action-bar -->
|
|
||||||
<style name="NativeScriptToolbarStyleBase" parent="Widget.AppCompat.Toolbar">
|
|
||||||
<item name="android:background">@color/ns_primary</item>
|
|
||||||
<item name="theme">@style/ThemeOverlay.AppCompat.ActionBar</item>
|
|
||||||
<item name="popupTheme">@style/ThemeOverlay.AppCompat</item>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style name="NativeScriptToolbarStyle" parent="NativeScriptToolbarStyleBase">
|
|
||||||
</style>
|
|
||||||
</resources>
|
|
544
app/app.scss
|
@ -13,13 +13,15 @@ $grayL1: #e0e0e0;
|
||||||
$grayL2: #eeeeee;
|
$grayL2: #eeeeee;
|
||||||
$grayL3: #f5f5f5;
|
$grayL3: #f5f5f5;
|
||||||
$grayL4: #fafafa;
|
$grayL4: #fafafa;
|
||||||
|
$orange400: #ff7043;
|
||||||
$orange: #ff7043;
|
$orange500: #ff5722;
|
||||||
$paleOrange: #fbe9e7;
|
|
||||||
|
|
||||||
// Global SCSS styling
|
// Global SCSS styling
|
||||||
// @see https://docs.nativescript.org/ui/styling
|
// @see https://docs.nativescript.org/ui/styling
|
||||||
|
|
||||||
|
// * {
|
||||||
|
// font-size: 16;
|
||||||
|
// }
|
||||||
Page {
|
Page {
|
||||||
font-family: "Orkney-Regular";
|
font-family: "Orkney-Regular";
|
||||||
}
|
}
|
||||||
|
@ -32,13 +34,19 @@ Page {
|
||||||
.bx {
|
.bx {
|
||||||
font-family: "boxicons";
|
font-family: "boxicons";
|
||||||
font-size: 24;
|
font-size: 24;
|
||||||
|
vertical-alignment: center;
|
||||||
|
&.small {
|
||||||
|
padding: 0;
|
||||||
|
font-size: 16;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ns-light {
|
.ns-light {
|
||||||
Page,
|
Page,
|
||||||
ActionBar,
|
ActionBar,
|
||||||
SearchBar,
|
SearchBar,
|
||||||
TabView {
|
TabView,
|
||||||
|
ListPicker {
|
||||||
color: $grayD4;
|
color: $grayD4;
|
||||||
background: $grayL4;
|
background: $grayL4;
|
||||||
}
|
}
|
||||||
|
@ -53,49 +61,57 @@ Page {
|
||||||
.fieldLabel {
|
.fieldLabel {
|
||||||
background: $grayL4;
|
background: $grayL4;
|
||||||
}
|
}
|
||||||
.view-reference-text,
|
.referenceItem,
|
||||||
.view-reference-container {
|
.recipeText,
|
||||||
|
.overviewItem,
|
||||||
|
.recipeItem {
|
||||||
background: white;
|
background: white;
|
||||||
}
|
}
|
||||||
.option-highlight {
|
.option-highlight,
|
||||||
|
.selected-sd-item {
|
||||||
background: $grayL2;
|
background: $grayL2;
|
||||||
}
|
}
|
||||||
.sd-item,
|
.sd-item,
|
||||||
.sd-group-header,
|
.sd-group-header,
|
||||||
.recipe-time {
|
.time .bx {
|
||||||
color: $grayD2;
|
color: $grayD2;
|
||||||
}
|
}
|
||||||
|
.fab-button {
|
||||||
|
color: white;
|
||||||
|
background-color: $orange500;
|
||||||
|
}
|
||||||
.option,
|
.option,
|
||||||
.icon-option {
|
.icon-option {
|
||||||
.bx,
|
.bx,
|
||||||
.option-info {
|
.option-info {
|
||||||
color: $grayD2;
|
color: $grayD2;
|
||||||
}
|
}
|
||||||
.option-title {
|
|
||||||
color: $grayD4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.view-imageHolder,
|
.imageHolder {
|
||||||
.recipeImgContainer {
|
|
||||||
color: $grayL1;
|
color: $grayL1;
|
||||||
background: $grayL2;
|
background: $grayL2;
|
||||||
}
|
}
|
||||||
.view-other {
|
.count {
|
||||||
color: $grayD2;
|
|
||||||
}
|
|
||||||
.view-count {
|
|
||||||
color: $grayL4;
|
color: $grayL4;
|
||||||
background: $grayD4;
|
background: $grayD4;
|
||||||
}
|
}
|
||||||
.view-instruction {
|
.instruction {
|
||||||
border-color: $grayD4;
|
border-color: $grayD4;
|
||||||
}
|
}
|
||||||
|
.text-btn,
|
||||||
|
.group-header,
|
||||||
|
.category,
|
||||||
|
ActivityIndicator,
|
||||||
|
.selected-sd-item {
|
||||||
|
color: $orange500;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.ns-dark {
|
.ns-dark {
|
||||||
Page,
|
Page,
|
||||||
ActionBar,
|
ActionBar,
|
||||||
SearchBar,
|
SearchBar,
|
||||||
TabView {
|
TabView,
|
||||||
|
ListPicker {
|
||||||
color: $grayL4;
|
color: $grayL4;
|
||||||
background: $grayD4;
|
background: $grayD4;
|
||||||
}
|
}
|
||||||
|
@ -106,50 +122,57 @@ Page {
|
||||||
.hr {
|
.hr {
|
||||||
border-color: #111;
|
border-color: #111;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sd,
|
.sd,
|
||||||
.fieldLabel {
|
.fieldLabel {
|
||||||
background: $grayD4;
|
background: $grayD4;
|
||||||
}
|
}
|
||||||
.recipe-li,
|
.referenceItem,
|
||||||
|
.recipeText,
|
||||||
|
.overviewItem,
|
||||||
|
.recipeItem,
|
||||||
.option-highlight,
|
.option-highlight,
|
||||||
.view-reference-text,
|
.appIconContainer {
|
||||||
.view-reference-container {
|
|
||||||
background: $grayD3;
|
background: $grayD3;
|
||||||
}
|
}
|
||||||
.sd-item,
|
.sd-item,
|
||||||
.sd-group-header,
|
.sd-group-header,
|
||||||
.recipe-time {
|
.time .bx {
|
||||||
color: $grayL2;
|
color: $grayL2;
|
||||||
}
|
}
|
||||||
|
.selected-sd-item {
|
||||||
|
background: #111;
|
||||||
|
}
|
||||||
|
.fab-button {
|
||||||
|
color: #111;
|
||||||
|
background: $orange400;
|
||||||
|
}
|
||||||
.option,
|
.option,
|
||||||
.icon-option {
|
.icon-option {
|
||||||
.bx,
|
.bx,
|
||||||
.option-info {
|
.option-info {
|
||||||
color: $grayL2;
|
color: $grayL2;
|
||||||
}
|
}
|
||||||
.option-title {
|
|
||||||
color: $grayL4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.view-imageHolder,
|
.imageHolder {
|
||||||
.recipeImgContainer {
|
|
||||||
color: $grayD4;
|
color: $grayD4;
|
||||||
background: #111;
|
background: #111;
|
||||||
}
|
}
|
||||||
.view-other {
|
.count {
|
||||||
color: $grayL2;
|
|
||||||
}
|
|
||||||
.view-count {
|
|
||||||
color: $grayD4;
|
color: $grayD4;
|
||||||
background: $grayL4;
|
background: $grayL4;
|
||||||
}
|
}
|
||||||
.view-instruction {
|
.instruction {
|
||||||
border-color: $grayL4;
|
border-color: $grayL4;
|
||||||
}
|
}
|
||||||
|
.text-btn,
|
||||||
|
.group-header,
|
||||||
|
.category,
|
||||||
|
ActivityIndicator,
|
||||||
|
.selected-sd-item {
|
||||||
|
color: $orange400;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// -----------------------------
|
||||||
// Elements
|
// Elements
|
||||||
TextField,
|
TextField,
|
||||||
TextView,
|
TextView,
|
||||||
|
@ -173,131 +196,118 @@ TabView {
|
||||||
margin-top: 16;
|
margin-top: 16;
|
||||||
}
|
}
|
||||||
.fieldLabel {
|
.fieldLabel {
|
||||||
font-size: 13;
|
font-size: 12;
|
||||||
margin-left: 8;
|
margin-left: 8;
|
||||||
padding: 0 8;
|
padding: 0 8;
|
||||||
}
|
}
|
||||||
// DateTimePicker
|
// -----------------------------
|
||||||
.date-time-picker,
|
|
||||||
.date-time-picker-spinners {
|
|
||||||
color: $grayD4;
|
|
||||||
background: $grayL4;
|
|
||||||
&.ns-dark {
|
|
||||||
color: $grayL4;
|
|
||||||
background: $grayD4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.ns-dark .date-time-picker-spinners {
|
|
||||||
color: $grayL4;
|
|
||||||
background: $grayD4;
|
|
||||||
}
|
|
||||||
// ActionBar
|
// ActionBar
|
||||||
ActionBar {
|
ActionBar {
|
||||||
width: 100%;
|
|
||||||
margin: 24 0 0 0;
|
margin: 24 0 0 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
height: 64;
|
height: 64;
|
||||||
.bx {
|
.bx {
|
||||||
padding: 16 12;
|
|
||||||
vertical-alignment: center;
|
|
||||||
}
|
|
||||||
.leftAction {
|
|
||||||
padding: 16 16 16 4;
|
padding: 16 16 16 4;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
vertical-alignment: center;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
padding-left: 8;
|
||||||
|
text-align: left;
|
||||||
|
font-size: 18;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.actionBarContainer {
|
// -----------------------------
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
SearchBar {
|
|
||||||
width: 100%;
|
|
||||||
font-size: 16;
|
|
||||||
}
|
|
||||||
.title {
|
|
||||||
padding-left: 8;
|
|
||||||
text-align: left;
|
|
||||||
font-size: 18;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Side Drawer
|
// Side Drawer
|
||||||
.sd {
|
.sd {
|
||||||
margin-top: 24;
|
padding: 32 8 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sd-item {
|
.sd-item {
|
||||||
border-radius: 4;
|
border-radius: 4;
|
||||||
padding: 0 16;
|
padding: 0 16;
|
||||||
height: 48;
|
height: 48;
|
||||||
font-size: 16;
|
|
||||||
vertical-alignment: center;
|
vertical-alignment: center;
|
||||||
// prettier-ignore
|
.bx {
|
||||||
.bx, Label {
|
font-size: 24;
|
||||||
vertical-alignment: center;
|
|
||||||
}
|
}
|
||||||
&.selected-sd-item {
|
// prettier-ignore
|
||||||
background: $paleOrange;
|
Label {
|
||||||
color: $orange;
|
font-size: 16;
|
||||||
|
vertical-alignment: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.sd-group-header {
|
.sd-group-header {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 8 8 16;
|
padding: 8 8 16;
|
||||||
font-size: 12;
|
|
||||||
}
|
}
|
||||||
|
// -----------------------------
|
||||||
// Home
|
// HOME
|
||||||
RadListView {
|
.emptyState,
|
||||||
margin: 8 0 128;
|
.noResult {
|
||||||
}
|
|
||||||
.recipe-li {
|
|
||||||
background: white;
|
|
||||||
margin: 8 16;
|
|
||||||
border-radius: 6;
|
|
||||||
.recipe-info {
|
|
||||||
margin: 4;
|
|
||||||
}
|
|
||||||
.recipe-cat {
|
|
||||||
font-size: 12;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
.recipe-title {
|
|
||||||
font-size: 16;
|
|
||||||
line-height: 4;
|
|
||||||
margin: 0;
|
|
||||||
padding: 4 0;
|
|
||||||
}
|
|
||||||
.recipe-time {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
.recipe-cat {
|
|
||||||
color: $orange;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.emptyState {
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
.noResults {
|
.noResult {
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
font-size: 16;
|
|
||||||
line-height: 8;
|
line-height: 8;
|
||||||
padding: 64 16;
|
padding: 64 16;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
font-size: 16;
|
||||||
horizontal-alignment: center;
|
horizontal-alignment: center;
|
||||||
// vertical-alignment: center;
|
vertical-alignment: center;
|
||||||
.title {
|
.icon {
|
||||||
font-size: 20;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.bx {
|
|
||||||
font-size: 64;
|
font-size: 64;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: $gray;
|
color: $gray;
|
||||||
margin-bottom: 16;
|
margin-bottom: 16;
|
||||||
}
|
}
|
||||||
|
.title {
|
||||||
|
font-size: 20;
|
||||||
|
text-align: center;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
horizontal-alignment: center;
|
||||||
|
.bx {
|
||||||
|
font-size: 24;
|
||||||
|
vertical-alignment: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// -----------------------------
|
||||||
|
// Recipe Items
|
||||||
|
RadListView {
|
||||||
|
margin: 0 0 128;
|
||||||
|
font-size: 16;
|
||||||
|
}
|
||||||
|
.recipeItem {
|
||||||
|
margin: 8 16;
|
||||||
|
border-radius: 6;
|
||||||
|
.recipeInfo {
|
||||||
|
margin: 4;
|
||||||
|
.category,
|
||||||
|
.time {
|
||||||
|
font-size: 12;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
margin: 0;
|
||||||
|
padding: 4 0;
|
||||||
|
}
|
||||||
|
.timeContainer {
|
||||||
|
padding: 0;
|
||||||
|
.time {
|
||||||
|
padding: 0 0 0 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.imageHolder {
|
||||||
|
vertical-alignment: center;
|
||||||
|
border-radius: 6 0 0 6;
|
||||||
|
// prettier-ignore
|
||||||
|
Image {
|
||||||
|
border-radius: 6 0 0 6;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.swipe-item {
|
.swipe-item {
|
||||||
margin: 0 8;
|
margin: 0 8;
|
||||||
|
@ -306,167 +316,166 @@ RadListView {
|
||||||
height: 128;
|
height: 128;
|
||||||
border-radius: 6;
|
border-radius: 6;
|
||||||
}
|
}
|
||||||
.recipeImgContainer {
|
// -----------------------------
|
||||||
vertical-alignment: center;
|
// SETTINGS
|
||||||
// prettier-ignore
|
|
||||||
Image {
|
|
||||||
border-radius: 6 0 0 6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Settings
|
|
||||||
.group-header {
|
.group-header {
|
||||||
padding: 8;
|
padding: 8;
|
||||||
color: #ff7043;
|
|
||||||
}
|
}
|
||||||
.main-container {
|
.main-container {
|
||||||
padding: 16 8 128;
|
padding: 16 8 128;
|
||||||
.option {
|
.option {
|
||||||
padding: 16;
|
|
||||||
border-radius: 4;
|
|
||||||
font-size: 16;
|
font-size: 16;
|
||||||
|
padding: 16;
|
||||||
.bx {
|
.bx {
|
||||||
margin: 0 24 0 0;
|
margin: 0 24 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.option-info {
|
.option-info {
|
||||||
font-size: 12;
|
font-size: 12;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// -----------------------------
|
||||||
// About
|
// ABOUT
|
||||||
.app-icon-container {
|
.appIconContainer {
|
||||||
margin: 32 0;
|
padding: 32 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
.app-icon {
|
.appIcon {
|
||||||
width: 56;
|
width: 56;
|
||||||
height: 56;
|
height: 56;
|
||||||
margin: 0 6 0 0;
|
margin: 0 6 0 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
.app-name {
|
.appName {
|
||||||
font-size: 24;
|
font-size: 24;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.icon-option {
|
// -----------------------------
|
||||||
padding: 16;
|
// VIEW RECIPE
|
||||||
border-radius: 4;
|
.viewRecipe {
|
||||||
.bx {
|
.category,
|
||||||
margin: 0 24 0 0;
|
.time,
|
||||||
}
|
.ingredient,
|
||||||
.option-title {
|
.ingredient-check {
|
||||||
font-size: 16;
|
font-size: 16;
|
||||||
}
|
}
|
||||||
}
|
.category {
|
||||||
|
margin: 0 8;
|
||||||
// View Recipe
|
}
|
||||||
|
.time {
|
||||||
.view-cat {
|
margin: 0 8;
|
||||||
font-size: 16;
|
.bx {
|
||||||
color: #ff7043;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
.view-other {
|
}
|
||||||
font-size: 16;
|
.title {
|
||||||
}
|
font-size: 22;
|
||||||
.view-title {
|
line-height: 6;
|
||||||
font-size: 22;
|
}
|
||||||
line-height: 6;
|
.overviewContainer {
|
||||||
margin-bottom: 16;
|
margin-top: 12;
|
||||||
}
|
.overviewItem {
|
||||||
.view-ingredient {
|
border-radius: 6;
|
||||||
font-size: 16;
|
padding: 8;
|
||||||
line-height: 6;
|
margin: 8;
|
||||||
padding-bottom: 12;
|
android-elevation: 1;
|
||||||
}
|
.bx {
|
||||||
.activity-indicator {
|
color: $gray;
|
||||||
background: #ff7043;
|
width: 24;
|
||||||
}
|
horizontal-alignment: left;
|
||||||
|
}
|
||||||
.view-count {
|
.itemCount {
|
||||||
font-size: 12;
|
font-size: 16;
|
||||||
width: 24;
|
padding: 8 4 4;
|
||||||
height: 24;
|
}
|
||||||
padding-top: 4%;
|
}
|
||||||
margin: 0 0 0 8;
|
}
|
||||||
text-align: center;
|
.ingredient,
|
||||||
border-radius: 100;
|
.ingredient-check {
|
||||||
&.note {
|
line-height: 6;
|
||||||
clip-path: polygon(
|
padding-bottom: 12;
|
||||||
5% 0,
|
}
|
||||||
95% 0,
|
.ingredient-check {
|
||||||
100% 5%,
|
margin-bottom: 12;
|
||||||
100% 65%,
|
}
|
||||||
65% 100%,
|
.count {
|
||||||
5% 100%,
|
width: 24;
|
||||||
0 95%,
|
height: 24;
|
||||||
0 5%
|
padding-top: 4%;
|
||||||
);
|
margin: 0 0 0 8;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 100;
|
||||||
|
&.square {
|
||||||
|
clip-path: polygon(
|
||||||
|
5% 0,
|
||||||
|
95% 0,
|
||||||
|
100% 5%,
|
||||||
|
100% 65%,
|
||||||
|
65% 100%,
|
||||||
|
5% 100%,
|
||||||
|
0 95%,
|
||||||
|
0 5%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.instruction,
|
||||||
|
.note,
|
||||||
|
.reference {
|
||||||
|
font-size: 16;
|
||||||
|
line-height: 6;
|
||||||
|
padding: 2 0 14 36;
|
||||||
|
margin: 0 0 0 19;
|
||||||
|
border-width: 0 0 0 2;
|
||||||
|
}
|
||||||
|
.instruction.noBorder {
|
||||||
|
border-color: transparent;
|
||||||
|
}
|
||||||
|
.note {
|
||||||
|
border-width: 0;
|
||||||
|
}
|
||||||
|
.referenceItem {
|
||||||
|
padding: 14 16;
|
||||||
|
margin: 8 16 8;
|
||||||
|
border-radius: 6;
|
||||||
|
font-size: 16;
|
||||||
|
.bx {
|
||||||
|
font-size: 24;
|
||||||
|
}
|
||||||
|
.recipeLink {
|
||||||
|
padding: 0 16 0 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.recipeText {
|
||||||
|
font-size: 16;
|
||||||
|
line-height: 6;
|
||||||
|
padding: 16;
|
||||||
|
margin: 8 16 8;
|
||||||
|
border-radius: 6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.view-instruction,
|
// -----------------------------
|
||||||
.view-note,
|
// FAB
|
||||||
.view-reference {
|
|
||||||
font-size: 16;
|
|
||||||
line-height: 6;
|
|
||||||
padding: 2 0 14 36;
|
|
||||||
margin: 0 0 0 19;
|
|
||||||
border-width: 0 0 0 2;
|
|
||||||
}
|
|
||||||
.view-instruction.instructionWOBorder {
|
|
||||||
border-color: transparent;
|
|
||||||
}
|
|
||||||
.view-note {
|
|
||||||
border-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.view-reference-container {
|
|
||||||
padding: 14 16;
|
|
||||||
margin: 8 16 8;
|
|
||||||
border-radius: 6;
|
|
||||||
}
|
|
||||||
.view-reference {
|
|
||||||
padding: 0 16 0 0;
|
|
||||||
margin: 0;
|
|
||||||
border-width: 0;
|
|
||||||
}
|
|
||||||
.view-reference-text {
|
|
||||||
font-size: 16;
|
|
||||||
line-height: 6;
|
|
||||||
padding: 16;
|
|
||||||
margin: 8 16 8;
|
|
||||||
border-radius: 6;
|
|
||||||
}
|
|
||||||
// .view-copyReference {
|
|
||||||
// color: #ff7043;
|
|
||||||
// }
|
|
||||||
#btnFabContainer {
|
#btnFabContainer {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
// Edit Recipe
|
|
||||||
.fab-button {
|
.fab-button {
|
||||||
color: #fff;
|
|
||||||
height: 56;
|
height: 56;
|
||||||
width: 56;
|
width: 56;
|
||||||
background-color: #ff7043;
|
|
||||||
vertical-alignment: center;
|
|
||||||
// horizontal-alignment: center;
|
|
||||||
border-radius: 28;
|
border-radius: 28;
|
||||||
padding: 16;
|
padding: 16;
|
||||||
margin: 16;
|
margin: 16;
|
||||||
|
vertical-alignment: center;
|
||||||
android-elevation: 6;
|
android-elevation: 6;
|
||||||
&.negative {
|
|
||||||
background-color: #e53935;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// -----------------------------
|
||||||
|
// EDIT RECIPE
|
||||||
.sectionTitle {
|
.sectionTitle {
|
||||||
font-size: 20;
|
font-size: 20;
|
||||||
}
|
}
|
||||||
.sec-btn {
|
.text-btn {
|
||||||
font-size: 14;
|
font-size: 14;
|
||||||
color: #ff7043;
|
horizontal-alignment: left;
|
||||||
text-align: left;
|
|
||||||
padding: 16;
|
padding: 16;
|
||||||
margin: 8 0 0 0;
|
margin: 8 0 0 0;
|
||||||
}
|
}
|
||||||
|
@ -474,14 +483,13 @@ RadListView {
|
||||||
padding: 4;
|
padding: 4;
|
||||||
margin-top: 16;
|
margin-top: 16;
|
||||||
}
|
}
|
||||||
|
// -----------------------------
|
||||||
// Dialogs
|
// DIALOGS
|
||||||
.dialogContainer {
|
.dialogContainer {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
&.light {
|
color: $grayD4;
|
||||||
color: $grayD4;
|
background: $grayL4;
|
||||||
background: $grayL4;
|
font-size: 16;
|
||||||
}
|
|
||||||
&.dark {
|
&.dark {
|
||||||
color: $grayL4;
|
color: $grayL4;
|
||||||
background: $grayD4;
|
background: $grayD4;
|
||||||
|
@ -490,60 +498,62 @@ RadListView {
|
||||||
padding: 24 24 12;
|
padding: 24 24 12;
|
||||||
font-size: 20;
|
font-size: 20;
|
||||||
}
|
}
|
||||||
.dialogInputField {
|
.dialogInput {
|
||||||
padding: 0 24 16;
|
padding: 0 24 16;
|
||||||
}
|
}
|
||||||
.dialogDescription {
|
.dialogDescription {
|
||||||
font-size: 16;
|
|
||||||
line-height: 4;
|
line-height: 4;
|
||||||
padding: 0 24 16;
|
padding: 0 24 16;
|
||||||
}
|
}
|
||||||
.action {
|
|
||||||
padding: 24 24 24 8;
|
|
||||||
font-size: 12;
|
|
||||||
color: #ff7043;
|
|
||||||
}
|
|
||||||
.actionItem {
|
.actionItem {
|
||||||
width: 100%;
|
padding: 8 24;
|
||||||
font-size: 16;
|
margin: 0;
|
||||||
padding: 8 20;
|
|
||||||
}
|
}
|
||||||
.cancel {
|
.actionsContainer {
|
||||||
padding: 24;
|
padding: 24;
|
||||||
|
}
|
||||||
|
.action {
|
||||||
font-size: 12;
|
font-size: 12;
|
||||||
color: #ff7043;
|
color: #ff7043;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ActivityIndicator {
|
|
||||||
color: #ff7043;
|
|
||||||
padding: 16 12;
|
|
||||||
margin: 16 10 16 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vue Transitions
|
// -----------------------------
|
||||||
|
ActivityIndicator {
|
||||||
|
width: 24;
|
||||||
|
height: 24;
|
||||||
|
margin: 16;
|
||||||
|
}
|
||||||
|
// -----------------------------
|
||||||
|
// Transitions
|
||||||
.bounce-enter-active {
|
.bounce-enter-active {
|
||||||
animation-name: bounce-in;
|
animation-name: bounce-in;
|
||||||
animation-duration: 0.5s;
|
animation-duration: 1s;
|
||||||
animation-fill-mode: forwards;
|
animation-fill-mode: forwards;
|
||||||
animation-timing-function: ease-out;
|
animation-timing-function: ease-in-out;
|
||||||
}
|
}
|
||||||
.bounce-leave-active {
|
.bounce-leave-active {
|
||||||
animation-name: bounce-in;
|
animation-name: bounce-in;
|
||||||
animation-duration: 0.1s;
|
animation-duration: 0.1s;
|
||||||
animation-fill-mode: forwards;
|
animation-fill-mode: forwards;
|
||||||
animation-direction: reverse;
|
animation-direction: reverse;
|
||||||
animation-timing-function: ease-in;
|
animation-timing-function: ease;
|
||||||
}
|
}
|
||||||
@keyframes bounce-in {
|
@keyframes bounce-in {
|
||||||
0% {
|
0% {
|
||||||
transform: scale(0);
|
transform: scale(0);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
25% {
|
||||||
50% {
|
|
||||||
transform: scale(1.2);
|
transform: scale(1.2);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
50% {
|
||||||
|
transform: scale(0.9);
|
||||||
|
}
|
||||||
|
75% {
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
|
@ -554,7 +564,7 @@ ActivityIndicator {
|
||||||
animation-duration: 1s;
|
animation-duration: 1s;
|
||||||
animation-delay: 0.25s;
|
animation-delay: 0.25s;
|
||||||
animation-fill-mode: forwards;
|
animation-fill-mode: forwards;
|
||||||
animation-timing-function: ease;
|
animation-timing-function: ease-in-out;
|
||||||
}
|
}
|
||||||
.dolly-leave-active {
|
.dolly-leave-active {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
|
@ -1,86 +1,81 @@
|
||||||
<template>
|
<template>
|
||||||
<Page @loaded="initializePage">
|
<Page @loaded="initializePage">
|
||||||
<ActionBar :flat="viewIsScrolled ? false : true">
|
<ActionBar :flat="viewIsScrolled ? false : true">
|
||||||
<!-- Settings Actionbar -->
|
<GridLayout rows="*" columns="auto, *">
|
||||||
<GridLayout rows="*" columns="auto, *" class="actionBarContainer">
|
|
||||||
<Label
|
<Label
|
||||||
class="bx leftAction"
|
class="bx"
|
||||||
:text="icon.menu"
|
:text="icon.menu"
|
||||||
automationText="Menu"
|
automationText="Back"
|
||||||
@tap="showDrawer"
|
@tap="showDrawer"
|
||||||
col="0"
|
col="0"
|
||||||
/>
|
/>
|
||||||
<Label class="title orkm" text="About" col="1" />
|
<Label class="title orkm" text="About" col="1" />
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</ActionBar>
|
</ActionBar>
|
||||||
<ScrollView scrollBarIndicatorVisible="false">
|
<ScrollView scrollBarIndicatorVisible="false" @scroll="onScroll">
|
||||||
<StackLayout class="main-container">
|
<StackLayout class="main-container">
|
||||||
<StackLayout
|
<StackLayout
|
||||||
horizontalAlignment="center"
|
horizontalAlignment="center"
|
||||||
orientation="horizontal"
|
orientation="horizontal"
|
||||||
class="app-icon-container"
|
class="appIconContainer"
|
||||||
>
|
>
|
||||||
<Image src="res://icon" class="app-icon" stretch="fill" />
|
<Image src="res://icon" class="appIcon" stretch="fill" />
|
||||||
<Label
|
<Label
|
||||||
text="EnRecipes"
|
text="EnRecipes"
|
||||||
verticalAlignment="center"
|
verticalAlignment="center"
|
||||||
class="app-name orkb"
|
class="appName orkb"
|
||||||
/>
|
/>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<StackLayout orientation="horizontal" class="icon-option">
|
<StackLayout orientation="horizontal" class="option">
|
||||||
<Label verticalAlignment="center" class="bx" :text="icon.info" />
|
<Label class="bx" :text="icon.info" />
|
||||||
<StackLayout>
|
<StackLayout>
|
||||||
<Label text="Version" class="option-title" />
|
<Label text="Version" />
|
||||||
<Label text="1.0.0" class="option-info" textWrap="true" />
|
<Label :text="getVersion" class="option-info" textWrap="true" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<StackLayout
|
<StackLayout
|
||||||
orientation="horizontal"
|
orientation="horizontal"
|
||||||
class="icon-option"
|
class="option"
|
||||||
@tap="openURL($event, 'https://github.com/vishnuraghavb/enrecipes')"
|
@tap="openURL($event, 'https://github.com/vishnuraghavb/enrecipes')"
|
||||||
>
|
>
|
||||||
<Label class="bx" :text="icon.link" />
|
<Label class="bx" :text="icon.link" />
|
||||||
<Label text="View project on GitHub" class="option-title" />
|
<Label text="View project on GitHub" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<StackLayout
|
<StackLayout
|
||||||
orientation="horizontal"
|
orientation="horizontal"
|
||||||
class="icon-option"
|
class="option"
|
||||||
@tap="openURL($event, 'https://t.me/enrecipes')"
|
@tap="openURL($event, 'https://t.me/enrecipes')"
|
||||||
>
|
>
|
||||||
<Label class="bx" :text="icon.telegram" />
|
<Label class="bx" :text="icon.telegram" />
|
||||||
<Label text="Join the telegram group" class="option-title" />
|
<Label text="Join the Telegram group" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<!-- <StackLayout orientation="horizontal" class="icon-option">
|
|
||||||
<Label class="bx" :text="icon.file" />
|
|
||||||
<Label text="Licenses" class="option-title" />
|
|
||||||
</StackLayout> -->
|
|
||||||
|
|
||||||
<StackLayout class="hr m-10"></StackLayout>
|
<StackLayout class="hr m-10"></StackLayout>
|
||||||
|
|
||||||
<Label text="Author" class="group-header" />
|
<Label text="Author" class="group-header" />
|
||||||
<StackLayout
|
<StackLayout
|
||||||
orientation="horizontal"
|
orientation="horizontal"
|
||||||
class="icon-option"
|
class="option"
|
||||||
@tap="openURL($event, 'https://www.vishnuraghav.com')"
|
@tap="openURL($event, 'https://www.vishnuraghav.com')"
|
||||||
>
|
>
|
||||||
<Label class="bx" :text="icon.user" />
|
<Label class="bx" :text="icon.user" />
|
||||||
<Label text="Vishnu Raghav" class="option-title" />
|
<Label text="Vishnu Raghav" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<StackLayout
|
<StackLayout
|
||||||
orientation="horizontal"
|
orientation="horizontal"
|
||||||
class="icon-option"
|
class="option"
|
||||||
@tap="openURL($event, 'https://github.com/vishnuraghavb')"
|
@tap="openURL($event, 'https://github.com/vishnuraghavb')"
|
||||||
>
|
>
|
||||||
<Label class="bx" :text="icon.link" />
|
<Label class="bx" :text="icon.link" />
|
||||||
<Label text="Follow on GitHub" class="option-title" />
|
<Label text="Follow on GitHub" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<StackLayout
|
<StackLayout
|
||||||
orientation="horizontal"
|
orientation="horizontal"
|
||||||
class="icon-option"
|
class="option"
|
||||||
@tap="openURL($event, 'https://mastodon.social/@vishnuraghavb')"
|
@tap="openURL($event, 'https://mastodon.social/@vishnuraghavb')"
|
||||||
>
|
>
|
||||||
<Label class="bx" :text="icon.link" />
|
<Label class="bx" :text="icon.link" />
|
||||||
<Label text="Follow on Mastodon" class="option-title" />
|
<Label text="Follow on Mastodon" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
@ -88,18 +83,33 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { Utils } from "@nativescript/core"
|
import { Utils, Application } from "@nativescript/core"
|
||||||
import { mapState, mapActions } from "vuex"
|
import { mapState, mapActions } from "vuex"
|
||||||
export default {
|
export default {
|
||||||
props: ["highlight", "viewIsScrolled", "showDrawer", "title"],
|
props: ["highlight", "showDrawer", "title"],
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(["icon", "currentComponent"]),
|
...mapState(["icon", "currentComponent"]),
|
||||||
|
getVersion() {
|
||||||
|
let ctx = Application.android.context
|
||||||
|
return ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), 0)
|
||||||
|
.versionName
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
viewIsScrolled: false,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions(["setCurrentComponentAction"]),
|
...mapActions(["setCurrentComponentAction"]),
|
||||||
initializePage() {
|
initializePage() {
|
||||||
this.setCurrentComponentAction("About")
|
this.setCurrentComponentAction("About")
|
||||||
},
|
},
|
||||||
|
onScroll(args) {
|
||||||
|
args.scrollY
|
||||||
|
? (this.viewIsScrolled = true)
|
||||||
|
: (this.viewIsScrolled = false)
|
||||||
|
},
|
||||||
openURL(args, url) {
|
openURL(args, url) {
|
||||||
this.highlight(args)
|
this.highlight(args)
|
||||||
Utils.openUrl(url)
|
Utils.openUrl(url)
|
||||||
|
|
|
@ -8,27 +8,22 @@
|
||||||
gesturesEnabled="true"
|
gesturesEnabled="true"
|
||||||
drawerTransition="SlideInOnTopTransition"
|
drawerTransition="SlideInOnTopTransition"
|
||||||
>
|
>
|
||||||
<GridLayout
|
<GridLayout rows="*, auto" columns="*" ~drawerContent class="sd">
|
||||||
rows="*, auto"
|
|
||||||
columns="*"
|
|
||||||
~drawerContent
|
|
||||||
padding="8"
|
|
||||||
class="sd"
|
|
||||||
>
|
|
||||||
<StackLayout row="0">
|
<StackLayout row="0">
|
||||||
<StackLayout
|
<GridLayout
|
||||||
|
rows="48"
|
||||||
|
columns="auto, 24, *"
|
||||||
v-for="(item, index) in topmenu"
|
v-for="(item, index) in topmenu"
|
||||||
:key="index"
|
:key="index"
|
||||||
@tap="navigateTo(item.component, false, false)"
|
@tap="navigateTo(item.component, false, false)"
|
||||||
orientation="horizontal"
|
|
||||||
class="sd-item orkm"
|
class="sd-item orkm"
|
||||||
:class="{
|
:class="{
|
||||||
'selected-sd-item': currentComponent === item.component,
|
'selected-sd-item': currentComponent === item.component,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<Label class="bx" :text="icon[item.icon]" margin="0 24 0 0" />
|
<Label col="0" row="0" class="bx" :text="icon[item.icon]" />
|
||||||
<Label :text="item.title" />
|
<Label col="2" row="0" :text="item.title" />
|
||||||
</StackLayout>
|
</GridLayout>
|
||||||
<StackLayout class="hr m-10"></StackLayout>
|
<StackLayout class="hr m-10"></StackLayout>
|
||||||
<GridLayout
|
<GridLayout
|
||||||
class="sd-group-header orkm"
|
class="sd-group-header orkm"
|
||||||
|
@ -64,7 +59,7 @@
|
||||||
<Label col="1" :text="item" />
|
<Label col="1" :text="item" />
|
||||||
<Label
|
<Label
|
||||||
v-if="catEditMode"
|
v-if="catEditMode"
|
||||||
@tap="editCategory(item)"
|
@tap="renameCategory(item)"
|
||||||
col="2"
|
col="2"
|
||||||
class="bx"
|
class="bx"
|
||||||
:text="icon.edit"
|
:text="icon.edit"
|
||||||
|
@ -100,7 +95,7 @@
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
|
|
||||||
<GridLayout ~mainContent rows="*" columns="*">
|
<GridLayout ~mainContent rows="*" columns="*">
|
||||||
<Frame ref="mainFrame" id="main-frame">
|
<Frame row="0" col="0" ref="mainFrame" id="main-frame">
|
||||||
<!-- Home -->
|
<!-- Home -->
|
||||||
<EnRecipes
|
<EnRecipes
|
||||||
ref="enrecipes"
|
ref="enrecipes"
|
||||||
|
@ -179,7 +174,13 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(["icon", "recipes", "categories", "currentComponent"]),
|
...mapState([
|
||||||
|
"icon",
|
||||||
|
"recipes",
|
||||||
|
"categories",
|
||||||
|
"yieldUnits",
|
||||||
|
"currentComponent",
|
||||||
|
]),
|
||||||
categoriesWithRecipes() {
|
categoriesWithRecipes() {
|
||||||
let arr = this.recipes.map((e) => {
|
let arr = this.recipes.map((e) => {
|
||||||
return e.category
|
return e.category
|
||||||
|
@ -192,11 +193,12 @@ export default {
|
||||||
"setCurrentComponentAction",
|
"setCurrentComponentAction",
|
||||||
"initializeRecipes",
|
"initializeRecipes",
|
||||||
"initializeCategories",
|
"initializeCategories",
|
||||||
|
"initializeYieldUnits",
|
||||||
"renameCategoryAction",
|
"renameCategoryAction",
|
||||||
]),
|
]),
|
||||||
toggleCatEdit() {
|
toggleCatEdit() {
|
||||||
this.catEditMode = !this.catEditMode
|
this.catEditMode = !this.catEditMode
|
||||||
this.setComponent("EnRecipes")
|
if (this.selectedCategory) this.setComponent("EnRecipes")
|
||||||
this.filterFavorites = this.filterTrylater = false
|
this.filterFavorites = this.filterTrylater = false
|
||||||
this.selectedCategory = null
|
this.selectedCategory = null
|
||||||
this.$refs.enrecipes.updateFilter()
|
this.$refs.enrecipes.updateFilter()
|
||||||
|
@ -204,7 +206,7 @@ export default {
|
||||||
setComponent(comp) {
|
setComponent(comp) {
|
||||||
this.setCurrentComponentAction(comp)
|
this.setCurrentComponentAction(comp)
|
||||||
},
|
},
|
||||||
editCategory(category) {
|
renameCategory(category) {
|
||||||
this.releaseGlobalBackEvent()
|
this.releaseGlobalBackEvent()
|
||||||
this.$showModal(PromptDialog, {
|
this.$showModal(PromptDialog, {
|
||||||
props: {
|
props: {
|
||||||
|
@ -217,6 +219,7 @@ export default {
|
||||||
if (newCategory.length) {
|
if (newCategory.length) {
|
||||||
this.renameCategoryAction({ current: category, updated: newCategory })
|
this.renameCategoryAction({ current: category, updated: newCategory })
|
||||||
this.catEditMode = false
|
this.catEditMode = false
|
||||||
|
this.navigateTo(newCategory, false, true)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -279,7 +282,6 @@ export default {
|
||||||
frame: "main-frame",
|
frame: "main-frame",
|
||||||
props: {
|
props: {
|
||||||
highlight: this.highlight,
|
highlight: this.highlight,
|
||||||
viewIsScrolled: this.viewIsScrolled,
|
|
||||||
showDrawer: this.showDrawer,
|
showDrawer: this.showDrawer,
|
||||||
restartApp: this.restartApp,
|
restartApp: this.restartApp,
|
||||||
hijackGlobalBackEvent: this.hijackGlobalBackEvent,
|
hijackGlobalBackEvent: this.hijackGlobalBackEvent,
|
||||||
|
@ -340,6 +342,7 @@ export default {
|
||||||
setTimeout((e) => Theme.setMode(Theme[themeName]), 50)
|
setTimeout((e) => Theme.setMode(Theme[themeName]), 50)
|
||||||
if (!this.recipes.length) this.initializeRecipes()
|
if (!this.recipes.length) this.initializeRecipes()
|
||||||
if (!this.categories.length) this.initializeCategories()
|
if (!this.categories.length) this.initializeCategories()
|
||||||
|
if (!this.yieldUnits.length) this.initializeYieldUnits()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<Page @loaded="initialize" @unloaded="releaseBackEvent">
|
<Page @loaded="initialize" @unloaded="releaseBackEvent">
|
||||||
<ActionBar :flat="viewIsScrolled ? false : true">
|
<ActionBar :flat="viewIsScrolled ? false : true">
|
||||||
<GridLayout rows="*" columns="auto, *, auto" class="actionBarContainer">
|
<GridLayout rows="*" columns="auto, *, auto">
|
||||||
<Label
|
<Label
|
||||||
class="bx leftAction"
|
class="bx"
|
||||||
:text="icon.back"
|
:text="icon.back"
|
||||||
automationText="Back"
|
automationText="Back"
|
||||||
col="0"
|
col="0"
|
||||||
|
@ -11,19 +11,20 @@
|
||||||
/>
|
/>
|
||||||
<Label class="title orkm" :text="title" col="1" />
|
<Label class="title orkm" :text="title" col="1" />
|
||||||
<Label
|
<Label
|
||||||
v-if="hasEnoughDetails"
|
v-if="hasEnoughDetails && !imageLoading"
|
||||||
class="bx"
|
class="bx"
|
||||||
:text="icon.save"
|
:text="icon.save"
|
||||||
col="2"
|
col="2"
|
||||||
@tap="saveRecipe"
|
@tap="saveOperation"
|
||||||
/>
|
/>
|
||||||
|
<ActivityIndicator col="2" v-if="imageLoading" :busy="imageLoading" />
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</ActionBar>
|
</ActionBar>
|
||||||
<AbsoluteLayout>
|
<GridLayout rows="*" columns="*">
|
||||||
<ScrollView
|
<ScrollView
|
||||||
width="100%"
|
row="0"
|
||||||
height="100%"
|
col="0"
|
||||||
@scroll="onScroll($event)"
|
@scroll="onScroll"
|
||||||
scrollBarIndicatorVisible="false"
|
scrollBarIndicatorVisible="false"
|
||||||
>
|
>
|
||||||
<StackLayout width="100%" padding="0 0 128">
|
<StackLayout width="100%" padding="0 0 128">
|
||||||
|
@ -32,7 +33,7 @@
|
||||||
<StackLayout
|
<StackLayout
|
||||||
width="100%"
|
width="100%"
|
||||||
:height="screenWidth"
|
:height="screenWidth"
|
||||||
class="view-imageHolder"
|
class="imageHolder"
|
||||||
verticalAlignment="center"
|
verticalAlignment="center"
|
||||||
>
|
>
|
||||||
<Image
|
<Image
|
||||||
|
@ -47,7 +48,7 @@
|
||||||
horizontalAlignment="center"
|
horizontalAlignment="center"
|
||||||
class="bx"
|
class="bx"
|
||||||
fontSize="160"
|
fontSize="160"
|
||||||
:text="icon.image"
|
:text="icon.food"
|
||||||
/>
|
/>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<StackLayout width="100%" :top="screenWidth - 42">
|
<StackLayout width="100%" :top="screenWidth - 42">
|
||||||
|
@ -55,7 +56,7 @@
|
||||||
<Label
|
<Label
|
||||||
v-if="showFab"
|
v-if="showFab"
|
||||||
horizontalAlignment="right"
|
horizontalAlignment="right"
|
||||||
@tap="photoHandler"
|
@tap="imageHandler"
|
||||||
class="bx fab-button"
|
class="bx fab-button"
|
||||||
:text="icon.camera"
|
:text="icon.camera"
|
||||||
androidElevation="6"
|
androidElevation="6"
|
||||||
|
@ -76,43 +77,41 @@
|
||||||
</AbsoluteLayout>
|
</AbsoluteLayout>
|
||||||
<AbsoluteLayout class="inputField">
|
<AbsoluteLayout class="inputField">
|
||||||
<TextField
|
<TextField
|
||||||
v-model="recipeContent.category"
|
:text="recipeContent.category"
|
||||||
editable="false"
|
editable="false"
|
||||||
@tap="showCategories()"
|
@tap="showCategories"
|
||||||
/>
|
/>
|
||||||
<Label top="0" class="fieldLabel" text="Category" />
|
<Label top="0" class="fieldLabel" text="Category" />
|
||||||
</AbsoluteLayout>
|
</AbsoluteLayout>
|
||||||
<GridLayout columns="*, 8, *">
|
<GridLayout columns="*, 8, *">
|
||||||
<AbsoluteLayout class="inputField" col="0">
|
<AbsoluteLayout class="inputField" col="0">
|
||||||
<TimePickerField
|
<TextField
|
||||||
titleTextColor="red"
|
v-model="recipeContent.yield.quantity"
|
||||||
timeFormat="HH:mm"
|
hint="1"
|
||||||
pickerTitle="Approx. preparation time"
|
keyboardType="number"
|
||||||
@timeChange="onPrepTimeChange"
|
/>
|
||||||
:time="recipeContent.prepTime"
|
<Label top="0" class="fieldLabel" text="Yield quantity" />
|
||||||
></TimePickerField>
|
|
||||||
<Label top="0" class="fieldLabel" text="Preparation time" />
|
|
||||||
</AbsoluteLayout>
|
</AbsoluteLayout>
|
||||||
<AbsoluteLayout class="inputField" col="2">
|
<AbsoluteLayout class="inputField" col="2">
|
||||||
<TimePickerField
|
<TextField
|
||||||
timeFormat="HH:mm"
|
:text="recipeContent.yield.unit"
|
||||||
pickerTitle="Approx. cooking time"
|
editable="false"
|
||||||
@timeChange="onCookTimeChange"
|
@tap="showYieldUnits"
|
||||||
:time="recipeContent.cookTime"
|
/>
|
||||||
></TimePickerField>
|
<Label top="0" class="fieldLabel" text="Yield measured in" />
|
||||||
<Label top="0" class="fieldLabel" text="Cooking time" />
|
|
||||||
</AbsoluteLayout>
|
</AbsoluteLayout>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<GridLayout columns="*, 16, *">
|
<GridLayout columns="*, 8, *">
|
||||||
<AbsoluteLayout class="inputField" col="0">
|
<AbsoluteLayout class="inputField" col="0">
|
||||||
<TextField
|
<TextField
|
||||||
width="100%"
|
:text="formattedTimeRequired"
|
||||||
keyboardType="number"
|
editable="false"
|
||||||
v-model="recipeContent.portionSize"
|
@tap="setTimeRequired"
|
||||||
/>
|
/>
|
||||||
<Label top="0" class="fieldLabel" text="Portion size" />
|
<Label top="0" class="fieldLabel" text="Time required" />
|
||||||
</AbsoluteLayout>
|
</AbsoluteLayout>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
|
|
||||||
<StackLayout class="hr" margin="24 16"></StackLayout>
|
<StackLayout class="hr" margin="24 16"></StackLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
|
||||||
|
@ -125,6 +124,7 @@
|
||||||
:key="index"
|
:key="index"
|
||||||
>
|
>
|
||||||
<TextField
|
<TextField
|
||||||
|
@loaded="focusField"
|
||||||
col="0"
|
col="0"
|
||||||
v-model="recipeContent.ingredients[index].item"
|
v-model="recipeContent.ingredients[index].item"
|
||||||
:hint="`Item ${index + 1}`"
|
:hint="`Item ${index + 1}`"
|
||||||
|
@ -153,7 +153,7 @@
|
||||||
/>
|
/>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<Label
|
<Label
|
||||||
class="sec-btn pull-left orkm"
|
class="text-btn orkm"
|
||||||
text="+ ADD INGREDIENT"
|
text="+ ADD INGREDIENT"
|
||||||
@tap="addIngredient()"
|
@tap="addIngredient()"
|
||||||
/>
|
/>
|
||||||
|
@ -170,6 +170,7 @@
|
||||||
:key="index"
|
:key="index"
|
||||||
>
|
>
|
||||||
<TextView
|
<TextView
|
||||||
|
@loaded="focusField"
|
||||||
col="0"
|
col="0"
|
||||||
:hint="`Step ${index + 1}`"
|
:hint="`Step ${index + 1}`"
|
||||||
v-model="recipeContent.instructions[index]"
|
v-model="recipeContent.instructions[index]"
|
||||||
|
@ -183,7 +184,7 @@
|
||||||
/>
|
/>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<Label
|
<Label
|
||||||
class="sec-btn pull-left orkm"
|
class="text-btn orkm"
|
||||||
text="+ ADD STEP"
|
text="+ ADD STEP"
|
||||||
@tap="addInstruction()"
|
@tap="addInstruction()"
|
||||||
/>
|
/>
|
||||||
|
@ -199,6 +200,7 @@
|
||||||
:key="index"
|
:key="index"
|
||||||
>
|
>
|
||||||
<TextView
|
<TextView
|
||||||
|
@loaded="focusField"
|
||||||
col="0"
|
col="0"
|
||||||
v-model="recipeContent.notes[index]"
|
v-model="recipeContent.notes[index]"
|
||||||
:hint="`Note ${index + 1}`"
|
:hint="`Note ${index + 1}`"
|
||||||
|
@ -211,11 +213,7 @@
|
||||||
@tap="removeNote(index)"
|
@tap="removeNote(index)"
|
||||||
/>
|
/>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<Label
|
<Label class="text-btn orkm" text="+ ADD NOTE" @tap="addNote()" />
|
||||||
class="sec-btn pull-left orkm"
|
|
||||||
text="+ ADD NOTE"
|
|
||||||
@tap="addNote()"
|
|
||||||
/>
|
|
||||||
<StackLayout class="hr" margin="24 16"></StackLayout>
|
<StackLayout class="hr" margin="24 16"></StackLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
|
||||||
|
@ -228,6 +226,7 @@
|
||||||
:key="index"
|
:key="index"
|
||||||
>
|
>
|
||||||
<TextView
|
<TextView
|
||||||
|
@loaded="focusField"
|
||||||
col="0"
|
col="0"
|
||||||
v-model="recipeContent.references[index]"
|
v-model="recipeContent.references[index]"
|
||||||
hint="Text or Website/Video URL"
|
hint="Text or Website/Video URL"
|
||||||
|
@ -241,7 +240,7 @@
|
||||||
/>
|
/>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<Label
|
<Label
|
||||||
class="sec-btn pull-left orkm"
|
class="text-btn orkm"
|
||||||
text="+ ADD REFERENCE"
|
text="+ ADD REFERENCE"
|
||||||
@tap="addReference()"
|
@tap="addReference()"
|
||||||
/>
|
/>
|
||||||
|
@ -249,11 +248,14 @@
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</AbsoluteLayout>
|
</GridLayout>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { WorkerService } from "../worker.service"
|
||||||
|
var workerService = new WorkerService()
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Screen,
|
Screen,
|
||||||
AndroidApplication,
|
AndroidApplication,
|
||||||
|
@ -261,14 +263,20 @@ import {
|
||||||
path,
|
path,
|
||||||
getFileAccess,
|
getFileAccess,
|
||||||
knownFolders,
|
knownFolders,
|
||||||
|
Utils,
|
||||||
|
File,
|
||||||
} from "@nativescript/core"
|
} from "@nativescript/core"
|
||||||
import { Mediafilepicker } from "nativescript-mediafilepicker"
|
import { Mediafilepicker } from "nativescript-mediafilepicker"
|
||||||
|
|
||||||
|
import { DateTimePicker, TimePickerField } from "@nativescript/datetimepicker"
|
||||||
|
|
||||||
import { mapState, mapActions } from "vuex"
|
import { mapState, mapActions } from "vuex"
|
||||||
|
|
||||||
import ActionDialog from "./modal/ActionDialog.vue"
|
import ActionDialog from "./modal/ActionDialog.vue"
|
||||||
import ConfirmDialog from "./modal/ConfirmDialog.vue"
|
import ConfirmDialog from "./modal/ConfirmDialog.vue"
|
||||||
import PromptDialog from "./modal/PromptDialog.vue"
|
import PromptDialog from "./modal/PromptDialog.vue"
|
||||||
|
import ListPicker from "./modal/ListPicker.vue"
|
||||||
|
import { create } from "domain"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ["recipeIndex", "recipeID", "selectedCategory"],
|
props: ["recipeIndex", "recipeID", "selectedCategory"],
|
||||||
|
@ -280,31 +288,36 @@ export default {
|
||||||
imageSrc: null,
|
imageSrc: null,
|
||||||
title: undefined,
|
title: undefined,
|
||||||
category: "Undefined",
|
category: "Undefined",
|
||||||
prepTime: "00:00",
|
timeRequired: "00:00",
|
||||||
cookTime: "00:00",
|
yield: {
|
||||||
portionSize: 1,
|
quantity: undefined,
|
||||||
ingredients: [
|
unit: "Servings",
|
||||||
{
|
},
|
||||||
item: "",
|
ingredients: [],
|
||||||
quantity: undefined,
|
instructions: [],
|
||||||
unit: "unit",
|
notes: [],
|
||||||
},
|
references: [],
|
||||||
],
|
|
||||||
instructions: [""],
|
|
||||||
notes: [""],
|
|
||||||
references: [""],
|
|
||||||
isFavorite: false,
|
isFavorite: false,
|
||||||
tried: false,
|
tried: false,
|
||||||
|
lastTried: null,
|
||||||
lastModified: null,
|
lastModified: null,
|
||||||
},
|
},
|
||||||
tempRecipeContent: {},
|
tempRecipeContent: {},
|
||||||
blockModal: false,
|
blockModal: false,
|
||||||
newRecipeID: null,
|
newRecipeID: null,
|
||||||
showFab: false,
|
showFab: false,
|
||||||
|
imageLoading: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(["icon", "units", "recipes", "categories", "currentComponent"]),
|
...mapState([
|
||||||
|
"icon",
|
||||||
|
"units",
|
||||||
|
"yieldUnits",
|
||||||
|
"recipes",
|
||||||
|
"categories",
|
||||||
|
"currentComponent",
|
||||||
|
]),
|
||||||
screenWidth() {
|
screenWidth() {
|
||||||
return Screen.mainScreen.widthDIPs
|
return Screen.mainScreen.widthDIPs
|
||||||
},
|
},
|
||||||
|
@ -314,6 +327,12 @@ export default {
|
||||||
JSON.stringify(this.tempRecipeContent)
|
JSON.stringify(this.tempRecipeContent)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
formattedTimeRequired() {
|
||||||
|
let t = this.recipeContent.timeRequired.split(":")
|
||||||
|
let h = parseInt(t[0])
|
||||||
|
let m = parseInt(t[1])
|
||||||
|
return h ? (m ? `${h}h ${m}m` : `${h}h`) : `${m}m`
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions([
|
...mapActions([
|
||||||
|
@ -321,10 +340,19 @@ export default {
|
||||||
"addRecipeAction",
|
"addRecipeAction",
|
||||||
"overwriteRecipeAction",
|
"overwriteRecipeAction",
|
||||||
"addCategoryAction",
|
"addCategoryAction",
|
||||||
|
"addYieldUnitAction",
|
||||||
]),
|
]),
|
||||||
initialize() {
|
initialize() {
|
||||||
this.showFab = true
|
this.showFab = true
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// HELPERS
|
||||||
|
focusField(args) {
|
||||||
|
if (!args.object.text) {
|
||||||
|
args.object.focus()
|
||||||
|
setTimeout((e) => Utils.ad.showSoftInput(args.object.android), 1)
|
||||||
|
}
|
||||||
|
},
|
||||||
getRandomID() {
|
getRandomID() {
|
||||||
let res = ""
|
let res = ""
|
||||||
let chars = "abcdefghijklmnopqrstuvwxyz0123456789"
|
let chars = "abcdefghijklmnopqrstuvwxyz0123456789"
|
||||||
|
@ -333,87 +361,41 @@ export default {
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
},
|
},
|
||||||
setTime(key, time) {
|
setTimeRequired() {
|
||||||
if (Date.parse(time)) {
|
let time = this.recipeContent.timeRequired.split(":")
|
||||||
let date = new Date(time)
|
let hr = time[0]
|
||||||
let h = date.getHours()
|
let min = time[1]
|
||||||
let m = date.getMinutes()
|
this.$showModal(ListPicker, {
|
||||||
|
props: {
|
||||||
this.recipeContent[key] =
|
title: "Approx. time required",
|
||||||
(h < 10 ? "0" + h : h) + ":" + (m < 10 ? "0" + m : m)
|
action: "SET",
|
||||||
}
|
selectedHr: hr,
|
||||||
},
|
selectedMin: min,
|
||||||
clearEmptyFields() {
|
},
|
||||||
if (!this.recipeContent.title) {
|
}).then((result) => {
|
||||||
this.recipeContent.title = "Untitled Recipe"
|
if (result) {
|
||||||
}
|
this.recipeContent.timeRequired = result
|
||||||
if (!this.recipeContent.portionSize) {
|
|
||||||
this.recipeContent.portionSize = 1
|
|
||||||
}
|
|
||||||
this.recipeContent.ingredients.forEach((e, i) => {
|
|
||||||
if (!e.item.length) {
|
|
||||||
this.recipeContent.ingredients.splice(i, 1)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
let vm = this
|
|
||||||
function removeEmpty(arr) {
|
|
||||||
vm.recipeContent[arr].forEach((e, i) => {
|
|
||||||
if (!e.length) {
|
|
||||||
vm.recipeContent[arr].splice(i, 1)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
removeEmpty("instructions")
|
|
||||||
removeEmpty("notes")
|
|
||||||
removeEmpty("references")
|
|
||||||
},
|
|
||||||
saveRecipe() {
|
|
||||||
console.log(
|
|
||||||
JSON.stringify(this.recipeContent),
|
|
||||||
JSON.stringify(this.tempRecipeContent)
|
|
||||||
)
|
|
||||||
this.clearEmptyFields()
|
|
||||||
this.recipeContent.lastModified = new Date()
|
|
||||||
if (this.recipeID) {
|
|
||||||
this.overwriteRecipeAction({
|
|
||||||
index: this.recipeIndex,
|
|
||||||
id: this.recipeID,
|
|
||||||
recipe: this.recipeContent,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
this.recipeContent.id = this.newRecipeID
|
|
||||||
this.addRecipeAction({
|
|
||||||
id: this.newRecipeID,
|
|
||||||
recipe: this.recipeContent,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (this.tempRecipeContent.imageSrc && !this.recipeContent.imageSrc) {
|
|
||||||
getFileAccess().deleteFile(this.tempRecipeContent.imageSrc)
|
|
||||||
}
|
|
||||||
this.$navigateBack()
|
|
||||||
},
|
|
||||||
onPrepTimeChange(args) {
|
|
||||||
this.setTime("prepTime", args.value)
|
|
||||||
},
|
|
||||||
onCookTimeChange(args) {
|
|
||||||
this.setTime("cookTime", args.value)
|
|
||||||
},
|
},
|
||||||
onScroll(args) {
|
onScroll(args) {
|
||||||
args.scrollY
|
args.scrollY
|
||||||
? (this.viewIsScrolled = true)
|
? (this.viewIsScrolled = true)
|
||||||
: (this.viewIsScrolled = false)
|
: (this.viewIsScrolled = false)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// DATA LIST
|
||||||
showCategories() {
|
showCategories() {
|
||||||
this.releaseBackEvent()
|
this.releaseBackEvent()
|
||||||
this.$showModal(ActionDialog, {
|
this.$showModal(ActionDialog, {
|
||||||
props: {
|
props: {
|
||||||
title: "Category",
|
title: "Category",
|
||||||
list: [...this.categories],
|
list: [...this.categories],
|
||||||
height: "60%",
|
height: "408",
|
||||||
action: "NEW CATEGORY",
|
action: "CREATE NEW",
|
||||||
},
|
},
|
||||||
}).then((action) => {
|
}).then((action) => {
|
||||||
if (action == "NEW CATEGORY") {
|
if (action == "CREATE NEW") {
|
||||||
this.$showModal(PromptDialog, {
|
this.$showModal(PromptDialog, {
|
||||||
props: {
|
props: {
|
||||||
title: "New category",
|
title: "New category",
|
||||||
|
@ -434,6 +416,52 @@ export default {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
showYieldUnits() {
|
||||||
|
this.releaseBackEvent()
|
||||||
|
this.$showModal(ActionDialog, {
|
||||||
|
props: {
|
||||||
|
title: "Yield measured in",
|
||||||
|
list: [...this.yieldUnits],
|
||||||
|
height: "408",
|
||||||
|
action: "CREATE NEW",
|
||||||
|
},
|
||||||
|
}).then((action) => {
|
||||||
|
if (action == "CREATE NEW") {
|
||||||
|
this.$showModal(PromptDialog, {
|
||||||
|
props: {
|
||||||
|
title: "New yield unit",
|
||||||
|
action: "ADD",
|
||||||
|
},
|
||||||
|
}).then((yieldUnit) => {
|
||||||
|
this.hijackBackEvent()
|
||||||
|
if (yieldUnit.length) {
|
||||||
|
this.recipeContent.yield.unit = yieldUnit
|
||||||
|
this.addYieldUnitAction(yieldUnit)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else if (action) {
|
||||||
|
this.recipeContent.yield.unit = action
|
||||||
|
this.hijackBackEvent()
|
||||||
|
} else {
|
||||||
|
this.hijackBackEvent()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
showUnits(e) {
|
||||||
|
this.releaseBackEvent()
|
||||||
|
this.$showModal(ActionDialog, {
|
||||||
|
props: {
|
||||||
|
title: "Unit",
|
||||||
|
list: [...this.units],
|
||||||
|
height: "408",
|
||||||
|
},
|
||||||
|
}).then((action) => {
|
||||||
|
this.hijackBackEvent()
|
||||||
|
if (action) e.object.text = action
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// NAVIGATION HANDLERS
|
||||||
navigateBack() {
|
navigateBack() {
|
||||||
if (this.hasEnoughDetails) {
|
if (this.hasEnoughDetails) {
|
||||||
this.blockModal = true
|
this.blockModal = true
|
||||||
|
@ -448,7 +476,7 @@ export default {
|
||||||
}).then((action) => {
|
}).then((action) => {
|
||||||
this.blockModal = false
|
this.blockModal = false
|
||||||
if (action) {
|
if (action) {
|
||||||
this.saveRecipe()
|
this.saveOperation()
|
||||||
} else if (action != null) {
|
} else if (action != null) {
|
||||||
this.$navigateBack()
|
this.$navigateBack()
|
||||||
this.releaseBackEvent()
|
this.releaseBackEvent()
|
||||||
|
@ -477,7 +505,9 @@ export default {
|
||||||
this.navigateBack()
|
this.navigateBack()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
photoHandler() {
|
|
||||||
|
// DATA HANDLERS
|
||||||
|
imageHandler() {
|
||||||
if (this.recipeContent.imageSrc) {
|
if (this.recipeContent.imageSrc) {
|
||||||
this.blockModal = true
|
this.blockModal = true
|
||||||
this.$showModal(ConfirmDialog, {
|
this.$showModal(ConfirmDialog, {
|
||||||
|
@ -489,17 +519,17 @@ export default {
|
||||||
}).then((action) => {
|
}).then((action) => {
|
||||||
this.blockModal = false
|
this.blockModal = false
|
||||||
if (action) {
|
if (action) {
|
||||||
this.takePicture()
|
this.imagePicker()
|
||||||
} else if (action != null) {
|
} else if (action != null) {
|
||||||
this.removePicture()
|
this.recipeContent.imageSrc = null
|
||||||
this.releaseBackEvent()
|
this.releaseBackEvent()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
this.takePicture()
|
this.imagePicker()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
takePicture() {
|
imagePicker() {
|
||||||
const vm = this
|
const vm = this
|
||||||
const mediafilepicker = new Mediafilepicker()
|
const mediafilepicker = new Mediafilepicker()
|
||||||
mediafilepicker.openImagePicker({
|
mediafilepicker.openImagePicker({
|
||||||
|
@ -511,36 +541,7 @@ export default {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
mediafilepicker.on("getFiles", (image) => {
|
mediafilepicker.on("getFiles", (image) => {
|
||||||
let result = image.object.get("results")[0].file
|
vm.recipeContent.imageSrc = image.object.get("results")[0].file
|
||||||
ImageSource.fromFile(result).then((savedImg) => {
|
|
||||||
let savedImgPath = path.join(
|
|
||||||
knownFolders.documents().getFolder("enrecipes").path,
|
|
||||||
`${vm.getRandomID()}.jpg`
|
|
||||||
)
|
|
||||||
savedImg.saveToFile(savedImgPath, "jpg")
|
|
||||||
vm.recipeContent.imageSrc = savedImgPath
|
|
||||||
})
|
|
||||||
})
|
|
||||||
mediafilepicker.on("error", function(res) {
|
|
||||||
let msg = res.object.get("msg")
|
|
||||||
console.log(msg)
|
|
||||||
})
|
|
||||||
|
|
||||||
mediafilepicker.on("cancel", function(res) {
|
|
||||||
let msg = res.object.get("msg")
|
|
||||||
console.log(msg)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
removePicture() {
|
|
||||||
confirm({
|
|
||||||
title: "Delete Photo",
|
|
||||||
message: "Are you sure you want to delete the recipe photo?",
|
|
||||||
okButtonText: "Delete",
|
|
||||||
cancelButtonText: "Cancel",
|
|
||||||
}).then((e) => {
|
|
||||||
if (e) {
|
|
||||||
this.recipeContent.imageSrc = null
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -576,18 +577,70 @@ export default {
|
||||||
this.recipeContent.references.splice(index, 1)
|
this.recipeContent.references.splice(index, 1)
|
||||||
},
|
},
|
||||||
|
|
||||||
showUnits(e) {
|
clearEmptyFields() {
|
||||||
this.releaseBackEvent()
|
if (!this.recipeContent.title)
|
||||||
this.$showModal(ActionDialog, {
|
this.recipeContent.title = "Untitled Recipe"
|
||||||
props: {
|
if (!this.recipeContent.yield.quantity)
|
||||||
title: "Unit",
|
this.recipeContent.yield.quantity = 1
|
||||||
list: [...this.units],
|
this.recipeContent.ingredients = this.recipeContent.ingredients.filter(
|
||||||
height: "75%",
|
(e) => e.item
|
||||||
},
|
)
|
||||||
}).then((action) => {
|
let vm = this
|
||||||
this.hijackBackEvent()
|
function clearEmpty(arr) {
|
||||||
if (action) e.object.text = action
|
vm.recipeContent[arr] = vm.recipeContent[arr].filter((e) => e)
|
||||||
|
}
|
||||||
|
clearEmpty("instructions")
|
||||||
|
clearEmpty("notes")
|
||||||
|
clearEmpty("references")
|
||||||
|
},
|
||||||
|
saveOperation() {
|
||||||
|
this.imageLoading = true
|
||||||
|
this.clearEmptyFields()
|
||||||
|
this.recipeContent.lastModified = new Date()
|
||||||
|
if (this.recipeContent.imageSrc) {
|
||||||
|
if (this.tempRecipeContent.imageSrc) {
|
||||||
|
if (this.tempRecipeContent.imageSrc !== this.recipeContent.imageSrc) {
|
||||||
|
getFileAccess().deleteFile(this.tempRecipeContent.imageSrc)
|
||||||
|
this.imageSaveOperation()
|
||||||
|
} else this.saveRecipe()
|
||||||
|
} else this.imageSaveOperation()
|
||||||
|
} else if (this.tempRecipeContent.imageSrc) {
|
||||||
|
getFileAccess().deleteFile(this.tempRecipeContent.imageSrc)
|
||||||
|
this.saveRecipe()
|
||||||
|
} else this.saveRecipe()
|
||||||
|
},
|
||||||
|
imageSaveOperation() {
|
||||||
|
let imgSavedToPath = path.join(
|
||||||
|
knownFolders.documents().getFolder("enrecipes").path,
|
||||||
|
`${this.getRandomID()}.jpg`
|
||||||
|
)
|
||||||
|
let workerService = new WorkerService()
|
||||||
|
let ImageProcessor = workerService.initImageProcessor()
|
||||||
|
ImageProcessor.postMessage({
|
||||||
|
imgFile: this.recipeContent.imageSrc,
|
||||||
|
imgSavedToPath,
|
||||||
})
|
})
|
||||||
|
ImageProcessor.onmessage = ({ data }) => {
|
||||||
|
this.recipeContent.imageSrc = imgSavedToPath
|
||||||
|
this.saveRecipe()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
saveRecipe() {
|
||||||
|
if (this.recipeID) {
|
||||||
|
this.overwriteRecipeAction({
|
||||||
|
index: this.recipeIndex,
|
||||||
|
id: this.recipeID,
|
||||||
|
recipe: this.recipeContent,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.recipeContent.id = this.newRecipeID
|
||||||
|
this.addRecipeAction({
|
||||||
|
id: this.newRecipeID,
|
||||||
|
recipe: this.recipeContent,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.imageLoading = false
|
||||||
|
this.$navigateBack()
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
@ -598,7 +651,10 @@ export default {
|
||||||
if (this.recipeID) {
|
if (this.recipeID) {
|
||||||
let recipe = this.recipes.filter((e) => e.id === this.recipeID)[0]
|
let recipe = this.recipes.filter((e) => e.id === this.recipeID)[0]
|
||||||
Object.assign(this.recipeContent, JSON.parse(JSON.stringify(recipe)))
|
Object.assign(this.recipeContent, JSON.parse(JSON.stringify(recipe)))
|
||||||
Object.assign(this.tempRecipeContent, JSON.parse(JSON.stringify(recipe)))
|
Object.assign(
|
||||||
|
this.tempRecipeContent,
|
||||||
|
JSON.parse(JSON.stringify(this.recipeContent))
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
Object.assign(
|
Object.assign(
|
||||||
this.tempRecipeContent,
|
this.tempRecipeContent,
|
||||||
|
|
|
@ -5,11 +5,10 @@
|
||||||
<GridLayout
|
<GridLayout
|
||||||
v-if="showSearch"
|
v-if="showSearch"
|
||||||
columns="auto, *"
|
columns="auto, *"
|
||||||
class="actionBarContainer"
|
|
||||||
verticalAlignment="center"
|
verticalAlignment="center"
|
||||||
>
|
>
|
||||||
<Label
|
<Label
|
||||||
class="bx leftAction"
|
class="bx"
|
||||||
:text="icon.back"
|
:text="icon.back"
|
||||||
automationText="Back"
|
automationText="Back"
|
||||||
col="0"
|
col="0"
|
||||||
|
@ -25,15 +24,11 @@
|
||||||
/>
|
/>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<!-- Home Actionbar -->
|
<!-- Home Actionbar -->
|
||||||
<GridLayout
|
<GridLayout v-else columns="auto, *, auto, auto">
|
||||||
v-else
|
|
||||||
columns="auto, *, auto, auto"
|
|
||||||
class="actionBarContainer"
|
|
||||||
>
|
|
||||||
<Label
|
<Label
|
||||||
class="bx leftAction"
|
class="bx"
|
||||||
:text="icon.menu"
|
:text="icon.menu"
|
||||||
automationText="Menu"
|
automationText="Back"
|
||||||
@tap="showDrawer"
|
@tap="showDrawer"
|
||||||
col="0"
|
col="0"
|
||||||
/>
|
/>
|
||||||
|
@ -62,19 +57,19 @@
|
||||||
swipeActions="true"
|
swipeActions="true"
|
||||||
@itemSwipeProgressChanged="onSwiping"
|
@itemSwipeProgressChanged="onSwiping"
|
||||||
@itemSwipeProgressEnded="onSwipeEnded"
|
@itemSwipeProgressEnded="onSwipeEnded"
|
||||||
@scrolled="onScroll($event)"
|
@scrolled="onScroll"
|
||||||
@itemTap="viewRecipe"
|
@itemTap="viewRecipe"
|
||||||
:filteringFunction="filterFunction"
|
:filteringFunction="filterFunction"
|
||||||
:sortingFunction="sortFunction"
|
:sortingFunction="sortFunction"
|
||||||
>
|
>
|
||||||
<v-template>
|
<v-template>
|
||||||
<GridLayout
|
<GridLayout
|
||||||
class="recipe-li"
|
class="recipeItem"
|
||||||
rows="112"
|
rows="112"
|
||||||
columns="112, *"
|
columns="112, *"
|
||||||
androidElevation="1"
|
androidElevation="2"
|
||||||
>
|
>
|
||||||
<GridLayout class="recipeImgContainer" rows="112" columns="112">
|
<GridLayout class="imageHolder" rows="112" columns="112">
|
||||||
<Image
|
<Image
|
||||||
row="0"
|
row="0"
|
||||||
col="0"
|
col="0"
|
||||||
|
@ -89,16 +84,19 @@
|
||||||
horizontalAlignment="center"
|
horizontalAlignment="center"
|
||||||
class="bx"
|
class="bx"
|
||||||
fontSize="56"
|
fontSize="56"
|
||||||
:text="icon.image"
|
:text="icon.food"
|
||||||
/>
|
/>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<StackLayout class="recipe-info" col="1">
|
<StackLayout class="recipeInfo" col="1">
|
||||||
<Label :text="recipe.category" class="orkm recipe-cat" />
|
<Label :text="recipe.category" class="orkm category" />
|
||||||
<Label :text="recipe.title" class="orkm recipe-title" />
|
<Label :text="recipe.title" class="orkm title" />
|
||||||
<Label
|
<StackLayout class="timeContainer" orientation="horizontal">
|
||||||
:text="recipeTotalTime(recipe.prepTime, recipe.cookTime)"
|
<Label class="bx small" :text="icon.time" />
|
||||||
class="h4 recipe-time"
|
<Label
|
||||||
/>
|
class="time"
|
||||||
|
:text="`${formattedTime(recipe.timeRequired).time}`"
|
||||||
|
/>
|
||||||
|
</StackLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</v-template>
|
</v-template>
|
||||||
|
@ -117,32 +115,30 @@
|
||||||
<StackLayout
|
<StackLayout
|
||||||
col="0"
|
col="0"
|
||||||
row="0"
|
row="0"
|
||||||
class="noResults"
|
class="noResult"
|
||||||
v-if="!recipes.length && !filterFavorites && !filterTrylater"
|
v-if="!recipes.length && !filterFavorites && !filterTrylater"
|
||||||
verticalAlignment="center"
|
|
||||||
>
|
>
|
||||||
|
<Label class="bx icon" :text="icon.plusCircle" textWrap="true" />
|
||||||
<Label
|
<Label
|
||||||
@tap="addRecipe"
|
class="title orkm"
|
||||||
class="bx"
|
|
||||||
:text="icon.plusCircle"
|
|
||||||
textWrap="true"
|
|
||||||
/>
|
|
||||||
<Label
|
|
||||||
class="title orkb"
|
|
||||||
text="Start adding your recipes!"
|
text="Start adding your recipes!"
|
||||||
textWrap="true"
|
textWrap="true"
|
||||||
/>
|
/>
|
||||||
<Label text='Tap the "+" icon to add a new recipe' textWrap="true" />
|
<StackLayout orientation="horizontal" horizontalAlignment="center">
|
||||||
|
<Label text="Use the " textWrap="true" />
|
||||||
|
<Label class="bx" :text="icon.plus" />
|
||||||
|
<Label text=" button to add a new recipe" textWrap="true" />
|
||||||
|
</StackLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<StackLayout
|
<StackLayout
|
||||||
col="0"
|
col="0"
|
||||||
row="0"
|
row="0"
|
||||||
class="noResults"
|
class="noResult"
|
||||||
v-if="!filteredRecipes.length && searchQuery"
|
v-if="!filteredRecipes.length && searchQuery"
|
||||||
verticalAlignment="top"
|
verticalAlignment="top"
|
||||||
>
|
>
|
||||||
<Label class="bx" :text="icon.search" textWrap="true" />
|
<Label class="bx icon" :text="icon.search" textWrap="true" />
|
||||||
<Label class="title orkb" text="No recipes found" textWrap="true" />
|
<Label class="title orkm" text="No recipes found" textWrap="true" />
|
||||||
<Label
|
<Label
|
||||||
:text="
|
:text="
|
||||||
`Your search "${searchQuery}" did not match any recipes${
|
`Your search "${searchQuery}" did not match any recipes${
|
||||||
|
@ -157,12 +153,11 @@
|
||||||
<StackLayout
|
<StackLayout
|
||||||
col="0"
|
col="0"
|
||||||
row="0"
|
row="0"
|
||||||
class="noResults"
|
class="noResult"
|
||||||
verticalAlignment="center"
|
|
||||||
v-if="!filteredRecipes.length && filterFavorites && !searchQuery"
|
v-if="!filteredRecipes.length && filterFavorites && !searchQuery"
|
||||||
>
|
>
|
||||||
<Label class="bx" :text="icon.heartOutline" textWrap="true" />
|
<Label class="bx icon" :text="icon.heartOutline" textWrap="true" />
|
||||||
<Label class="title orkb" text="No favorites yet!" textWrap="true" />
|
<Label class="title orkm" text="No favorites yet!" textWrap="true" />
|
||||||
<Label
|
<Label
|
||||||
text="Your favorited recipes will be listed here"
|
text="Your favorited recipes will be listed here"
|
||||||
textWrap="true"
|
textWrap="true"
|
||||||
|
@ -171,19 +166,18 @@
|
||||||
<StackLayout
|
<StackLayout
|
||||||
col="0"
|
col="0"
|
||||||
row="0"
|
row="0"
|
||||||
class="noResults"
|
class="noResult"
|
||||||
verticalAlignment="center"
|
|
||||||
v-if="!filteredRecipes.length && filterTrylater && !searchQuery"
|
v-if="!filteredRecipes.length && filterTrylater && !searchQuery"
|
||||||
>
|
>
|
||||||
<Label class="bx" :text="icon.trylaterOutline" textWrap="true" />
|
<Label class="bx icon" :text="icon.trylaterOutline" textWrap="true" />
|
||||||
<Label
|
<Label
|
||||||
class="title orkb"
|
class="title orkm"
|
||||||
text="No recipes here to try!"
|
text="Nothing to try next!"
|
||||||
textWrap="true"
|
textWrap="true"
|
||||||
/>
|
/>
|
||||||
<!-- text="Your Try later recipes will be listed here" -->
|
<!-- text="Your Try later recipes will be listed here" -->
|
||||||
<Label
|
<Label
|
||||||
text="Your recipes to try later will be listed here"
|
text="Recipes you wanted to try later will be listed here"
|
||||||
textWrap="true"
|
textWrap="true"
|
||||||
/>
|
/>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
@ -297,10 +291,10 @@ export default {
|
||||||
this.closeSearch()
|
this.closeSearch()
|
||||||
},
|
},
|
||||||
closeSearch() {
|
closeSearch() {
|
||||||
|
if (this.searchQuery) this.updateFilter()
|
||||||
this.searchQuery = ""
|
this.searchQuery = ""
|
||||||
Utils.ad.dismissSoftInput()
|
Utils.ad.dismissSoftInput()
|
||||||
this.showSearch = false
|
this.showSearch = false
|
||||||
this.updateFilter()
|
|
||||||
this.releaseLocalBackEvent()
|
this.releaseLocalBackEvent()
|
||||||
},
|
},
|
||||||
sortDialog() {
|
sortDialog() {
|
||||||
|
@ -309,7 +303,7 @@ export default {
|
||||||
props: {
|
props: {
|
||||||
title: "Sort by",
|
title: "Sort by",
|
||||||
list: ["Natural order", "Title", "Duration", "Last modified"],
|
list: ["Natural order", "Title", "Duration", "Last modified"],
|
||||||
height: "195", // 48*4 + 3 1dip separators
|
height: "216", // 54*4
|
||||||
},
|
},
|
||||||
}).then((action) => {
|
}).then((action) => {
|
||||||
if (action && action !== "Cancel" && this.sortType !== action) {
|
if (action && action !== "Cancel" && this.sortType !== action) {
|
||||||
|
@ -330,8 +324,8 @@ export default {
|
||||||
.localeCompare(otherItem.title.toLowerCase(), "en", {
|
.localeCompare(otherItem.title.toLowerCase(), "en", {
|
||||||
ignorePunctuation: true,
|
ignorePunctuation: true,
|
||||||
})
|
})
|
||||||
let d1 = this.recipeDuration(item.prepTime, item.cookTime)
|
let d1 = this.formattedTime(item.timeRequired).duration
|
||||||
let d2 = this.recipeDuration(otherItem.prepTime, otherItem.cookTime)
|
let d2 = this.formattedTime(otherItem.timeRequired).duration
|
||||||
let ld1 = new Date(item.lastModified)
|
let ld1 = new Date(item.lastModified)
|
||||||
let ld2 = new Date(otherItem.lastModified)
|
let ld2 = new Date(otherItem.lastModified)
|
||||||
switch (this.sortType) {
|
switch (this.sortType) {
|
||||||
|
@ -411,28 +405,29 @@ export default {
|
||||||
this.deletionDialogActive = false
|
this.deletionDialogActive = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
getTotalTime(prepTime, cookTime) {
|
// getTotalTime(prepTime, timeRequired) {
|
||||||
let pT = prepTime.split(":")
|
// let pT = prepTime.split(":")
|
||||||
let cT = cookTime.split(":")
|
// let cT = timeRequired.split(":")
|
||||||
let hrs = parseInt(pT[0]) + parseInt(cT[0])
|
// let hrs = parseInt(pT[0]) + parseInt(cT[0])
|
||||||
let mins = parseInt(pT[1]) + parseInt(cT[1])
|
// let mins = parseInt(pT[1]) + parseInt(cT[1])
|
||||||
if (mins > 60) {
|
// if (mins > 60) {
|
||||||
hrs += Math.floor(mins / 60)
|
// hrs += Math.floor(mins / 60)
|
||||||
mins -= 60
|
// mins -= 60
|
||||||
}
|
// }
|
||||||
|
// return {
|
||||||
|
// hrs,
|
||||||
|
// mins,
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
formattedTime(time) {
|
||||||
|
let t = time.split(":")
|
||||||
|
let h = parseInt(t[0])
|
||||||
|
let m = parseInt(t[1])
|
||||||
return {
|
return {
|
||||||
hrs,
|
time: h ? (m ? `${h}h ${m}m` : `${h}h`) : `${m}m`,
|
||||||
mins,
|
duration: `${h}${m}`,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
recipeTotalTime(prepTime, cookTime) {
|
|
||||||
let { hrs, mins } = this.getTotalTime(prepTime, cookTime)
|
|
||||||
return hrs ? `${hrs}h ${mins}m` : `${mins}m`
|
|
||||||
},
|
|
||||||
recipeDuration(prepTime, cookTime) {
|
|
||||||
let { hrs, mins } = this.getTotalTime(prepTime, cookTime)
|
|
||||||
return `${hrs}${mins}`
|
|
||||||
},
|
|
||||||
onScroll(args) {
|
onScroll(args) {
|
||||||
args.scrollOffset
|
args.scrollOffset
|
||||||
? (this.viewIsScrolled = true)
|
? (this.viewIsScrolled = true)
|
||||||
|
@ -448,7 +443,6 @@ export default {
|
||||||
// curve: "easeIn",
|
// curve: "easeIn",
|
||||||
// },
|
// },
|
||||||
props: {
|
props: {
|
||||||
viewIsScrolled: this.viewIsScrolled,
|
|
||||||
selectedCategory: this.selectedCategory,
|
selectedCategory: this.selectedCategory,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,56 +1,40 @@
|
||||||
<template>
|
<template>
|
||||||
<Page @loaded="initializePage">
|
<Page @loaded="initializePage">
|
||||||
<ActionBar :flat="viewIsScrolled ? false : true">
|
<ActionBar :flat="viewIsScrolled ? false : true">
|
||||||
<!-- Settings Actionbar -->
|
<GridLayout rows="*" columns="auto, *">
|
||||||
<GridLayout rows="*" columns="auto, *" class="actionBarContainer">
|
|
||||||
<Label
|
<Label
|
||||||
class="bx leftAction"
|
class="bx"
|
||||||
:text="icon.menu"
|
:text="icon.menu"
|
||||||
automationText="Menu"
|
automationText="Back"
|
||||||
@tap="showDrawer"
|
@tap="showDrawer"
|
||||||
col="0"
|
col="0"
|
||||||
/>
|
/>
|
||||||
<Label class="title orkm" text="Settings" col="1" />
|
<Label class="title orkm" text="Settings" col="1" />
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</ActionBar>
|
</ActionBar>
|
||||||
<ScrollView scrollBarIndicatorVisible="false">
|
<ScrollView scrollBarIndicatorVisible="false" @scroll="onScroll">
|
||||||
<StackLayout class="main-container">
|
<StackLayout class="main-container">
|
||||||
<Label text="Interface" class="group-header" />
|
<Label text="Interface" class="group-header" />
|
||||||
|
|
||||||
<StackLayout
|
<StackLayout
|
||||||
orientation="horizontal"
|
orientation="horizontal"
|
||||||
class="option"
|
class="option"
|
||||||
@tap="selectThemes"
|
@tap="selectThemes"
|
||||||
>
|
>
|
||||||
<!-- @tap="selectThemes" -->
|
|
||||||
<Label verticalAlignment="center" class="bx" :text="icon.theme" />
|
<Label verticalAlignment="center" class="bx" :text="icon.theme" />
|
||||||
<StackLayout>
|
<StackLayout>
|
||||||
<Label text="Theme" class="option-title" />
|
<Label text="Theme" class="option-title" />
|
||||||
<Label :text="themeName" class="option-info" textWrap="true" />
|
<Label :text="themeName" class="option-info" textWrap="true" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
|
||||||
<StackLayout class="hr m-10"></StackLayout>
|
<StackLayout class="hr m-10"></StackLayout>
|
||||||
|
|
||||||
<Label text="Backup/Restore" class="group-header" />
|
<Label text="Backup/Restore" class="group-header" />
|
||||||
<!-- <StackLayout
|
|
||||||
orientation="horizontal"
|
|
||||||
class="option"
|
|
||||||
@tap="selectBackupDir"
|
|
||||||
>
|
|
||||||
<Label verticalAlignment="center" class="bx" :text="icon.folder" />
|
|
||||||
<StackLayout>
|
|
||||||
<Label text="EnRecipes Backup Directory" class="option-title" />
|
|
||||||
<Label text="/storage/emulated/0/EnRecipes" class="option-info" />
|
|
||||||
</StackLayout>
|
|
||||||
</StackLayout> -->
|
|
||||||
<StackLayout orientation="horizontal" class="option" @tap="backupData">
|
<StackLayout orientation="horizontal" class="option" @tap="backupData">
|
||||||
<Label class="bx" :text="icon.backup" />
|
<Label class="bx" :text="icon.save" />
|
||||||
<Label text="Backup Data" class="option-title" />
|
<Label text="Backup data" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<StackLayout orientation="horizontal" class="option" @tap="restoreData">
|
<StackLayout orientation="horizontal" class="option" @tap="restoreData">
|
||||||
<Label class="bx" :text="icon.restore" />
|
<Label class="bx" :text="icon.restore" />
|
||||||
<Label text="Restore Data" class="option-title" />
|
<Label text="Restore data" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
@ -78,7 +62,6 @@ import { mapState, mapActions } from "vuex"
|
||||||
export default {
|
export default {
|
||||||
props: [
|
props: [
|
||||||
"highlight",
|
"highlight",
|
||||||
"viewIsScrolled",
|
|
||||||
"showDrawer",
|
"showDrawer",
|
||||||
"restartApp",
|
"restartApp",
|
||||||
"hijackGlobalBackEvent",
|
"hijackGlobalBackEvent",
|
||||||
|
@ -86,6 +69,7 @@ export default {
|
||||||
],
|
],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
viewIsScrolled: false,
|
||||||
interface: {
|
interface: {
|
||||||
theme: {
|
theme: {
|
||||||
title: "Theme",
|
title: "Theme",
|
||||||
|
@ -123,9 +107,10 @@ export default {
|
||||||
this.setCurrentComponentAction("Settings")
|
this.setCurrentComponentAction("Settings")
|
||||||
this.releaseGlobalBackEvent()
|
this.releaseGlobalBackEvent()
|
||||||
},
|
},
|
||||||
showDialog(args) {
|
onScroll(args) {
|
||||||
this.highlight(args)
|
args.scrollY
|
||||||
this.$showModal(ActionDialog)
|
? (this.viewIsScrolled = true)
|
||||||
|
: (this.viewIsScrolled = false)
|
||||||
},
|
},
|
||||||
selectThemes(args) {
|
selectThemes(args) {
|
||||||
this.highlight(args)
|
this.highlight(args)
|
||||||
|
@ -133,7 +118,7 @@ export default {
|
||||||
props: {
|
props: {
|
||||||
title: "Theme",
|
title: "Theme",
|
||||||
list: ["Light", "Dark"],
|
list: ["Light", "Dark"],
|
||||||
height: "97",
|
height: "108",
|
||||||
},
|
},
|
||||||
}).then((action) => {
|
}).then((action) => {
|
||||||
if (action && action !== "Cancel" && this.themeName !== action) {
|
if (action && action !== "Cancel" && this.themeName !== action) {
|
||||||
|
@ -177,10 +162,11 @@ export default {
|
||||||
android.os.Environment.DIRECTORY_DOWNLOADS
|
android.os.Environment.DIRECTORY_DOWNLOADS
|
||||||
).toString()
|
).toString()
|
||||||
let date = new Date()
|
let date = new Date()
|
||||||
|
let formattedDate = `${date.getFullYear()}${date.getMonth()}${date.getDate()}_${date.getHours()}-${date.getMinutes()}-${date.getSeconds()}`
|
||||||
let fromPath = path.join(knownFolders.documents().path, "enrecipes")
|
let fromPath = path.join(knownFolders.documents().path, "enrecipes")
|
||||||
let destPath = path.join(
|
let destPath = path.join(
|
||||||
sdDownloadPath,
|
sdDownloadPath,
|
||||||
`enrecipes_${date.toString()}.zip`
|
`EnRecipes-${formattedDate}.zip`
|
||||||
)
|
)
|
||||||
console.log(fromPath, destPath, sdDownloadPath)
|
console.log(fromPath, destPath, sdDownloadPath)
|
||||||
Zip.zip({
|
Zip.zip({
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<Page @loaded="initializePage">
|
<Page @loaded="initializePage">
|
||||||
<ActionBar height="152" margin="0" flat="true">
|
<ActionBar height="152" margin="0" flat="true" visibility="collapse">
|
||||||
<GridLayout
|
<GridLayout rows="24, 64, 64" columns="auto, *, auto,auto, auto">
|
||||||
rows="24, 64, 64"
|
|
||||||
columns="auto, *, auto,auto, auto"
|
|
||||||
class="actionBarContainer"
|
|
||||||
>
|
|
||||||
<Label
|
<Label
|
||||||
row="1"
|
row="1"
|
||||||
col="0"
|
col="0"
|
||||||
class="bx leftAction"
|
class="bx"
|
||||||
:text="icon.back"
|
:text="icon.back"
|
||||||
automationText="Back"
|
automationText="Back"
|
||||||
@tap="$navigateBack()"
|
@tap="$navigateBack()"
|
||||||
|
@ -50,11 +46,18 @@
|
||||||
:text="icon.edit"
|
:text="icon.edit"
|
||||||
@tap="editRecipe"
|
@tap="editRecipe"
|
||||||
/>
|
/>
|
||||||
<ActivityIndicator v-else row="1" col="4" :busy="busy" />
|
<ActivityIndicator v-else row="1" col="2" :busy="busy" />
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</ActionBar>
|
</ActionBar>
|
||||||
<AbsoluteLayout>
|
<AbsoluteLayout>
|
||||||
<TabView androidElevation="0" width="100%" height="100%">
|
<TabView
|
||||||
|
:selectedIndex="selectedTabIndex"
|
||||||
|
@selectedIndexChange="selectedIndexChange"
|
||||||
|
androidElevation="0"
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
class="viewRecipe"
|
||||||
|
>
|
||||||
<TabViewItem title="Overview">
|
<TabViewItem title="Overview">
|
||||||
<ScrollView scrollBarIndicatorVisible="false">
|
<ScrollView scrollBarIndicatorVisible="false">
|
||||||
<StackLayout>
|
<StackLayout>
|
||||||
|
@ -62,7 +65,7 @@
|
||||||
width="100%"
|
width="100%"
|
||||||
:height="screenWidth"
|
:height="screenWidth"
|
||||||
verticalAlignment="center"
|
verticalAlignment="center"
|
||||||
class="view-imageHolder"
|
class="imageHolder"
|
||||||
>
|
>
|
||||||
<Image
|
<Image
|
||||||
v-if="recipe.imageSrc"
|
v-if="recipe.imageSrc"
|
||||||
|
@ -76,69 +79,181 @@
|
||||||
horizontalAlignment="center"
|
horizontalAlignment="center"
|
||||||
class="bx"
|
class="bx"
|
||||||
fontSize="160"
|
fontSize="160"
|
||||||
:text="icon.image"
|
:text="icon.food"
|
||||||
/>
|
/>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<StackLayout margin="16 16 144">
|
<StackLayout margin="16 8 144">
|
||||||
<Label class="view-cat orkm" :text="recipe.category" />
|
<Label class="category orkm" :text="recipe.category" />
|
||||||
<Label
|
<Label
|
||||||
class="view-title orkm"
|
margin="0 8"
|
||||||
|
class="title orkm"
|
||||||
:text="recipe.title"
|
:text="recipe.title"
|
||||||
textWrap="true"
|
textWrap="true"
|
||||||
/>
|
/>
|
||||||
<Label
|
<Label class="time">
|
||||||
class="view-other"
|
<FormattedString>
|
||||||
:text="`Preparation time: ${getTime(recipe.prepTime)}`"
|
<Span text="Time required:"></Span>
|
||||||
/>
|
<Span
|
||||||
<Label
|
:text="` ${formattedTime(recipe.timeRequired)}`"
|
||||||
class="view-other"
|
></Span>
|
||||||
:text="`Cooking time: ${getTime(recipe.cookTime)}`"
|
</FormattedString>
|
||||||
/>
|
</Label>
|
||||||
|
<GridLayout
|
||||||
|
rows="auto, auto"
|
||||||
|
columns="*, *"
|
||||||
|
class="overviewContainer"
|
||||||
|
>
|
||||||
|
<StackLayout
|
||||||
|
class="overviewItem"
|
||||||
|
row="0"
|
||||||
|
col="0"
|
||||||
|
@tap="selectedTabIndex = 1"
|
||||||
|
>
|
||||||
|
<Label class="bx" :text="icon.item" />
|
||||||
|
<Label
|
||||||
|
class="itemCount"
|
||||||
|
:text="
|
||||||
|
`${recipe.ingredients.length} ${
|
||||||
|
recipe.ingredients.length == 1
|
||||||
|
? 'Ingredient'
|
||||||
|
: 'Ingredients'
|
||||||
|
}`
|
||||||
|
"
|
||||||
|
textWrap="true"
|
||||||
|
/>
|
||||||
|
</StackLayout>
|
||||||
|
<StackLayout
|
||||||
|
class="overviewItem"
|
||||||
|
row="0"
|
||||||
|
col="1"
|
||||||
|
@tap="selectedTabIndex = 2"
|
||||||
|
>
|
||||||
|
<Label class="bx" :text="icon.step" />
|
||||||
|
<Label
|
||||||
|
class="itemCount"
|
||||||
|
:text="
|
||||||
|
`${recipe.instructions.length} ${
|
||||||
|
recipe.instructions.length == 1 ? 'Step' : 'Steps'
|
||||||
|
}`
|
||||||
|
"
|
||||||
|
textWrap="true"
|
||||||
|
/>
|
||||||
|
</StackLayout>
|
||||||
|
<StackLayout
|
||||||
|
class="overviewItem"
|
||||||
|
row="1"
|
||||||
|
col="0"
|
||||||
|
@tap="selectedTabIndex = 3"
|
||||||
|
>
|
||||||
|
<Label class="bx" :text="icon.note" />
|
||||||
|
<Label
|
||||||
|
class="itemCount"
|
||||||
|
:text="
|
||||||
|
`${recipe.notes.length} ${
|
||||||
|
recipe.notes.length == 1 ? 'Note' : 'Notes'
|
||||||
|
}`
|
||||||
|
"
|
||||||
|
textWrap="true"
|
||||||
|
/>
|
||||||
|
</StackLayout>
|
||||||
|
<StackLayout
|
||||||
|
class="overviewItem"
|
||||||
|
row="1"
|
||||||
|
col="1"
|
||||||
|
@tap="selectedTabIndex = 4"
|
||||||
|
>
|
||||||
|
<Label class="bx" :text="icon.source" />
|
||||||
|
<Label
|
||||||
|
class="itemCount"
|
||||||
|
:text="
|
||||||
|
`${recipe.references.length} ${
|
||||||
|
recipe.references.length == 1
|
||||||
|
? 'Reference'
|
||||||
|
: 'References'
|
||||||
|
}`
|
||||||
|
"
|
||||||
|
textWrap="true"
|
||||||
|
/>
|
||||||
|
</StackLayout>
|
||||||
|
</GridLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</TabViewItem>
|
</TabViewItem>
|
||||||
<TabViewItem title="Ingredients">
|
<TabViewItem title="Ingredients">
|
||||||
<ScrollView scrollBarIndicatorVisible="false">
|
<ScrollView scrollBarIndicatorVisible="false">
|
||||||
<Label
|
<GridLayout
|
||||||
v-if="!recipe.ingredients.length"
|
v-if="!recipe.ingredients.length"
|
||||||
class="noResults"
|
rows="*"
|
||||||
text="Click the edit button to add ingredients to this recipe"
|
columns="*"
|
||||||
textWrap="true"
|
class="emptyState"
|
||||||
/>
|
>
|
||||||
<StackLayout v-else padding="16 16 124">
|
<StackLayout col="0" row="0" class="noResult">
|
||||||
|
<Label class="bx icon" :text="icon.item" textWrap="true" />
|
||||||
|
<StackLayout orientation="horizontal" class="title orkm">
|
||||||
|
<Label text="Use the " />
|
||||||
|
<Label class="bx" :text="icon.edit" />
|
||||||
|
<Label text=" button" />
|
||||||
|
</StackLayout>
|
||||||
|
<Label text="to add some ingredients" textWrap="true" />
|
||||||
|
</StackLayout>
|
||||||
|
</GridLayout>
|
||||||
|
<StackLayout v-else padding="16 16 134">
|
||||||
<AbsoluteLayout class="inputField">
|
<AbsoluteLayout class="inputField">
|
||||||
<TextField
|
<TextField
|
||||||
width="165"
|
width="50%"
|
||||||
v-model="portionScale"
|
v-model="yieldMultiplier"
|
||||||
keyboardType="number"
|
keyboardType="number"
|
||||||
/>
|
/>
|
||||||
<Label top="0" class="fieldLabel" text="Set portion size" />
|
|
||||||
</AbsoluteLayout>
|
|
||||||
<StackLayout margin="24 0 8 0">
|
|
||||||
<Label
|
<Label
|
||||||
class="view-title orkm"
|
top="0"
|
||||||
|
class="fieldLabel"
|
||||||
|
:text="`Required ${recipe.yield.unit.toLowerCase()}`"
|
||||||
|
/>
|
||||||
|
</AbsoluteLayout>
|
||||||
|
<StackLayout margin="24 0 16 0">
|
||||||
|
<Label
|
||||||
|
class="title orkm"
|
||||||
:text="
|
:text="
|
||||||
`Ingredients for ${portionScale}${
|
`Ingredients for ${
|
||||||
portionScale > 1
|
yieldMultiplier ? yieldMultiplier : 1
|
||||||
? ' portions'
|
} ${recipe.yield.unit.toLowerCase()}`
|
||||||
: portionScale == 0
|
|
||||||
? '1 portion'
|
|
||||||
: ' portion'
|
|
||||||
}`
|
|
||||||
"
|
"
|
||||||
textWrap="true"
|
textWrap="true"
|
||||||
/>
|
/>
|
||||||
<Label
|
</StackLayout>
|
||||||
class="view-ingredient"
|
<StackLayout
|
||||||
v-for="(item, index) in recipe.ingredients"
|
v-for="(item, index) in recipe.ingredients"
|
||||||
:key="index"
|
:key="index"
|
||||||
|
>
|
||||||
|
<check-box
|
||||||
|
v-if="filterTrylater"
|
||||||
|
class="ingredient-check"
|
||||||
|
checkPadding="16"
|
||||||
|
:fillColor="`${isLightMode ? '#ff5722' : '#ff7043'}`"
|
||||||
:text="
|
:text="
|
||||||
`${roundedQuantity(item.quantity)}${
|
`${
|
||||||
item.unit ? ' ' + item.unit : ''
|
roundedQuantity(item.quantity)
|
||||||
} ${item.item}`
|
? roundedQuantity(item.quantity) + ' '
|
||||||
|
: ''
|
||||||
|
}${roundedQuantity(item.quantity) ? item.unit + ' ' : ''}${
|
||||||
|
item.item
|
||||||
|
}`
|
||||||
"
|
"
|
||||||
|
/>
|
||||||
|
<Label
|
||||||
|
v-else
|
||||||
|
class="ingredient"
|
||||||
textWrap="true"
|
textWrap="true"
|
||||||
|
:text="
|
||||||
|
`${
|
||||||
|
roundedQuantity(item.quantity)
|
||||||
|
? roundedQuantity(item.quantity) + ' '
|
||||||
|
: ''
|
||||||
|
}${roundedQuantity(item.quantity) ? item.unit + ' ' : ''}${
|
||||||
|
item.item
|
||||||
|
}`
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
@ -146,12 +261,22 @@
|
||||||
</TabViewItem>
|
</TabViewItem>
|
||||||
<TabViewItem title="Instructions">
|
<TabViewItem title="Instructions">
|
||||||
<ScrollView scrollBarIndicatorVisible="false">
|
<ScrollView scrollBarIndicatorVisible="false">
|
||||||
<Label
|
<GridLayout
|
||||||
v-if="!recipe.instructions.length"
|
v-if="!recipe.instructions.length"
|
||||||
class="noResults"
|
rows="*"
|
||||||
text="Click the edit button to add instructions to this recipe"
|
columns="*"
|
||||||
textWrap="true"
|
class="emptyState"
|
||||||
/>
|
>
|
||||||
|
<StackLayout col="0" row="0" class="noResult">
|
||||||
|
<Label class="bx icon" :text="icon.step" textWrap="true" />
|
||||||
|
<StackLayout orientation="horizontal" class="title orkm">
|
||||||
|
<Label text="Use the " />
|
||||||
|
<Label class="bx" :text="icon.edit" />
|
||||||
|
<Label text=" button" />
|
||||||
|
</StackLayout>
|
||||||
|
<Label text="to add some instructions" textWrap="true" />
|
||||||
|
</StackLayout>
|
||||||
|
</GridLayout>
|
||||||
<StackLayout v-else padding="32 16 132">
|
<StackLayout v-else padding="32 16 132">
|
||||||
<GridLayout
|
<GridLayout
|
||||||
columns="auto ,*"
|
columns="auto ,*"
|
||||||
|
@ -161,10 +286,9 @@
|
||||||
<Label
|
<Label
|
||||||
col="0"
|
col="0"
|
||||||
colSpan="2"
|
colSpan="2"
|
||||||
class="view-instruction"
|
class="instruction"
|
||||||
:class="{
|
:class="{
|
||||||
instructionWOBorder:
|
noBorder: index === recipe.instructions.length - 1,
|
||||||
index === recipe.instructions.length - 1,
|
|
||||||
}"
|
}"
|
||||||
:text="instruction"
|
:text="instruction"
|
||||||
textWrap="true"
|
textWrap="true"
|
||||||
|
@ -172,7 +296,7 @@
|
||||||
<Label
|
<Label
|
||||||
verticalAlignment="top"
|
verticalAlignment="top"
|
||||||
horizontalAlignment="center"
|
horizontalAlignment="center"
|
||||||
class="view-count orkb"
|
class="count orkb"
|
||||||
col="0"
|
col="0"
|
||||||
:text="index + 1"
|
:text="index + 1"
|
||||||
/>
|
/>
|
||||||
|
@ -182,12 +306,22 @@
|
||||||
</TabViewItem>
|
</TabViewItem>
|
||||||
<TabViewItem title="Notes">
|
<TabViewItem title="Notes">
|
||||||
<ScrollView scrollBarIndicatorVisible="false">
|
<ScrollView scrollBarIndicatorVisible="false">
|
||||||
<Label
|
<GridLayout
|
||||||
v-if="!recipe.notes.length"
|
v-if="!recipe.notes.length"
|
||||||
class="noResults"
|
rows="*"
|
||||||
text="Click the edit button to add notes to this recipe"
|
columns="*"
|
||||||
textWrap="true"
|
class="emptyState"
|
||||||
/>
|
>
|
||||||
|
<StackLayout col="0" row="0" class="noResult">
|
||||||
|
<Label class="bx icon" :text="icon.note" textWrap="true" />
|
||||||
|
<StackLayout orientation="horizontal" class="title orkm">
|
||||||
|
<Label text="Use the " />
|
||||||
|
<Label class="bx" :text="icon.edit" />
|
||||||
|
<Label text=" button" />
|
||||||
|
</StackLayout>
|
||||||
|
<Label text="to add some notes" textWrap="true" />
|
||||||
|
</StackLayout>
|
||||||
|
</GridLayout>
|
||||||
<StackLayout v-else padding="32 16 132">
|
<StackLayout v-else padding="32 16 132">
|
||||||
<GridLayout
|
<GridLayout
|
||||||
columns="auto ,*"
|
columns="auto ,*"
|
||||||
|
@ -197,14 +331,14 @@
|
||||||
<Label
|
<Label
|
||||||
col="0"
|
col="0"
|
||||||
colSpan="2"
|
colSpan="2"
|
||||||
class="view-note"
|
class="note"
|
||||||
:text="note"
|
:text="note"
|
||||||
textWrap="true"
|
textWrap="true"
|
||||||
/>
|
/>
|
||||||
<Label
|
<Label
|
||||||
verticalAlignment="top"
|
verticalAlignment="top"
|
||||||
horizontalAlignment="center"
|
horizontalAlignment="center"
|
||||||
class="view-count note orkb"
|
class="count square orkb"
|
||||||
col="0"
|
col="0"
|
||||||
:text="index + 1"
|
:text="index + 1"
|
||||||
/>
|
/>
|
||||||
|
@ -214,12 +348,22 @@
|
||||||
</TabViewItem>
|
</TabViewItem>
|
||||||
<TabViewItem title="References">
|
<TabViewItem title="References">
|
||||||
<ScrollView scrollBarIndicatorVisible="false">
|
<ScrollView scrollBarIndicatorVisible="false">
|
||||||
<Label
|
<GridLayout
|
||||||
v-if="!recipe.references.length"
|
v-if="!recipe.references.length"
|
||||||
class="noResults"
|
rows="*"
|
||||||
text="Click the edit button to add references to this recipe"
|
columns="*"
|
||||||
textWrap="true"
|
class="emptyState"
|
||||||
/>
|
>
|
||||||
|
<StackLayout col="0" row="0" class="noResult">
|
||||||
|
<Label class="bx icon" :text="icon.source" textWrap="true" />
|
||||||
|
<StackLayout orientation="horizontal" class="title orkm">
|
||||||
|
<Label text="Use the " />
|
||||||
|
<Label class="bx" :text="icon.edit" />
|
||||||
|
<Label text=" button" />
|
||||||
|
</StackLayout>
|
||||||
|
<Label text="to add some references" textWrap="true" />
|
||||||
|
</StackLayout>
|
||||||
|
</GridLayout>
|
||||||
<StackLayout v-else padding="10 0 132">
|
<StackLayout v-else padding="10 0 132">
|
||||||
<StackLayout
|
<StackLayout
|
||||||
v-for="(reference, index) in recipe.references"
|
v-for="(reference, index) in recipe.references"
|
||||||
|
@ -228,27 +372,27 @@
|
||||||
<GridLayout
|
<GridLayout
|
||||||
v-if="isValidURL(reference)"
|
v-if="isValidURL(reference)"
|
||||||
columns="*, auto"
|
columns="*, auto"
|
||||||
class="view-reference-container"
|
class="referenceItem"
|
||||||
androidElevation="1"
|
androidElevation="1"
|
||||||
|
@longPress="copyURL($event, reference)"
|
||||||
>
|
>
|
||||||
<Label
|
<Label
|
||||||
col="0"
|
col="0"
|
||||||
verticalAlignment="center"
|
verticalAlignment="center"
|
||||||
class="view-reference"
|
class="recipeLink"
|
||||||
:text="reference"
|
:text="reference"
|
||||||
textWrap="false"
|
textWrap="false"
|
||||||
@tap="openURL($event, reference)"
|
|
||||||
/>
|
/>
|
||||||
<Label
|
<Label
|
||||||
col="1"
|
col="1"
|
||||||
class="view-copyReference bx"
|
class="bx"
|
||||||
:text="icon.copy"
|
:text="icon.source"
|
||||||
@tap="copyURL($event, reference)"
|
@tap="openURL($event, reference)"
|
||||||
/>
|
/>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<Label
|
<Label
|
||||||
v-else
|
v-else
|
||||||
class="view-reference-text"
|
class="recipeText"
|
||||||
:text="reference"
|
:text="reference"
|
||||||
textWrap="true"
|
textWrap="true"
|
||||||
/>
|
/>
|
||||||
|
@ -262,7 +406,7 @@
|
||||||
row="1"
|
row="1"
|
||||||
col="1"
|
col="1"
|
||||||
class="bx fab-button"
|
class="bx fab-button"
|
||||||
:text="icon.unchecked"
|
:text="icon.check"
|
||||||
@tap="recipeTried"
|
@tap="recipeTried"
|
||||||
v-if="filterTrylater"
|
v-if="filterTrylater"
|
||||||
/>
|
/>
|
||||||
|
@ -282,12 +426,19 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { Screen, Utils, ImageSource, Device, File } from "@nativescript/core"
|
import {
|
||||||
|
Screen,
|
||||||
|
Utils,
|
||||||
|
ImageSource,
|
||||||
|
Device,
|
||||||
|
File,
|
||||||
|
Color,
|
||||||
|
} from "@nativescript/core"
|
||||||
import { Feedback, FeedbackType, FeedbackPosition } from "nativescript-feedback"
|
import { Feedback, FeedbackType, FeedbackPosition } from "nativescript-feedback"
|
||||||
import * as application from "tns-core-modules/application"
|
|
||||||
import * as Toast from "nativescript-toast"
|
import * as Toast from "nativescript-toast"
|
||||||
import * as SocialShare from "nativescript-social-share-ns-7"
|
import * as SocialShare from "nativescript-social-share-ns-7"
|
||||||
import { setText } from "nativescript-clipboard"
|
import { setText } from "nativescript-clipboard"
|
||||||
|
import { Application } from "@nativescript/core"
|
||||||
|
|
||||||
import { mapState, mapActions } from "vuex"
|
import { mapState, mapActions } from "vuex"
|
||||||
|
|
||||||
|
@ -304,9 +455,10 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
busy: false,
|
busy: false,
|
||||||
portionScale: 1,
|
yieldMultiplier: 1,
|
||||||
recipe: null,
|
recipe: null,
|
||||||
showFab: false,
|
showFab: false,
|
||||||
|
selectedTabIndex: 0,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -314,11 +466,15 @@ export default {
|
||||||
screenWidth() {
|
screenWidth() {
|
||||||
return Screen.mainScreen.widthDIPs
|
return Screen.mainScreen.widthDIPs
|
||||||
},
|
},
|
||||||
isPortionScalePositive() {
|
isYieldMultiplierPositive() {
|
||||||
return this.portionScale && !isNaN(this.portionScale)
|
return this.yieldMultiplier && !isNaN(this.yieldMultiplier)
|
||||||
? parseFloat(this.portionScale)
|
? parseFloat(this.yieldMultiplier)
|
||||||
: 1
|
: 1
|
||||||
},
|
},
|
||||||
|
isLightMode() {
|
||||||
|
console.log(Application.systemAppearance())
|
||||||
|
return Application.systemAppearance() === "light"
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions(["toggleStateAction", "setCurrentComponentAction"]),
|
...mapActions(["toggleStateAction", "setCurrentComponentAction"]),
|
||||||
|
@ -328,42 +484,38 @@ export default {
|
||||||
setTimeout((e) => {
|
setTimeout((e) => {
|
||||||
this.setCurrentComponentAction("ViewRecipe")
|
this.setCurrentComponentAction("ViewRecipe")
|
||||||
}, 500)
|
}, 500)
|
||||||
this.portionScale = this.recipe.portionSize
|
this.yieldMultiplier = this.recipe.yield.quantity
|
||||||
this.showFab = true
|
this.showFab = true
|
||||||
this.showInfo()
|
|
||||||
},
|
},
|
||||||
niceDates(time) {
|
niceDates(time) {
|
||||||
let date = new Date(time)
|
let lastTried = new Date(time).getTime()
|
||||||
let diff = (new Date().getTime() - date.getTime()) / 1000
|
let now = new Date().getTime()
|
||||||
console.log(diff)
|
let midnight = new Date().setHours(0, 0, 0, 0)
|
||||||
|
let diff = (now - lastTried) / 1000
|
||||||
let dayDiff = Math.ceil(diff / 86400)
|
let dayDiff = Math.ceil(diff / 86400)
|
||||||
console.log(dayDiff)
|
|
||||||
|
|
||||||
if (isNaN(dayDiff) || dayDiff < 0) return ""
|
if (isNaN(dayDiff) || dayDiff < 0) return ""
|
||||||
|
|
||||||
return (
|
return (
|
||||||
(dayDiff == 0 &&
|
(diff < 86400 && lastTried > midnight && "today") ||
|
||||||
((diff < 60 && "just now") ||
|
|
||||||
(diff < 120 && "1 minute ago") ||
|
|
||||||
(diff < 3600 && Math.floor(diff / 60) + " minutes ago") ||
|
|
||||||
(diff < 7200 && "1 hour ago") ||
|
|
||||||
(diff < 86400 && Math.floor(diff / 3600) + " hours ago"))) ||
|
|
||||||
(dayDiff == 1 && "yesterday") ||
|
(dayDiff == 1 && "yesterday") ||
|
||||||
(dayDiff < 7 && dayDiff + " days ago") ||
|
(dayDiff < 7 && dayDiff + " days ago") ||
|
||||||
(dayDiff < 31 && Math.ceil(dayDiff / 7) + " week(s) ago") ||
|
(dayDiff < 31 && Math.round(dayDiff / 7) + " week(s) ago") ||
|
||||||
(dayDiff > 30 &&
|
(dayDiff < 366 && Math.round(dayDiff / 30) + " month(s) ago") ||
|
||||||
dayDiff < 365 &&
|
(dayDiff > 365 && "long time ago")
|
||||||
Math.round(dayDiff / 30) + " month(s) ago") ||
|
|
||||||
(dayDiff > 364 && Math.round(dayDiff / 365) + " year(s) ago")
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
selectedIndexChange(args) {
|
||||||
|
this.selectedTabIndex = args.object.selectedIndex
|
||||||
|
},
|
||||||
showInfo() {
|
showInfo() {
|
||||||
let feedback = new Feedback()
|
let feedback = new Feedback()
|
||||||
feedback.show({
|
feedback.show({
|
||||||
type: FeedbackType.Info,
|
title: `You tried this recipe ${this.niceDates(
|
||||||
message: `You tried this recipe ${this.niceDates(
|
this.recipe.lastTried
|
||||||
this.recipe.triedOn
|
|
||||||
)}!`,
|
)}!`,
|
||||||
|
titleColor: new Color(`${this.isLightMode ? "#fff" : "#111"}`),
|
||||||
|
backgroundColor: new Color(
|
||||||
|
`${this.isLightMode ? "#ff5722" : "#ff7043"}`
|
||||||
|
),
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
highlight(args) {
|
highlight(args) {
|
||||||
|
@ -374,8 +526,8 @@ export default {
|
||||||
roundedQuantity(quantity) {
|
roundedQuantity(quantity) {
|
||||||
return (
|
return (
|
||||||
Math.round(
|
Math.round(
|
||||||
(quantity / this.recipe.portionSize) *
|
(quantity / this.recipe.yield.quantity) *
|
||||||
this.isPortionScalePositive *
|
this.isYieldMultiplierPositive *
|
||||||
100
|
100
|
||||||
) / 100
|
) / 100
|
||||||
)
|
)
|
||||||
|
@ -399,14 +551,14 @@ export default {
|
||||||
shareRecipe() {
|
shareRecipe() {
|
||||||
let overview = `${
|
let overview = `${
|
||||||
this.recipe.title
|
this.recipe.title
|
||||||
} Recipe\n\nPreparation time: ${this.getTime(
|
} Recipe\n\nApprox. cooking time: ${this.formattedTime(
|
||||||
this.recipe.prepTime
|
this.recipe.timeRequired
|
||||||
)}\nCooking time: ${this.getTime(this.recipe.cookTime)}\n`
|
)}\n`
|
||||||
let shareContent = overview
|
let shareContent = overview
|
||||||
if (this.recipe.ingredients.length) {
|
if (this.recipe.ingredients.length) {
|
||||||
let ingredients = `\n\nIngredients for ${this.recipe.portionSize} ${
|
let ingredients = `\n\nIngredients for ${
|
||||||
this.recipe.portionSize === 1 ? "postion:" : "portions:"
|
this.yieldMultiplier
|
||||||
}\n\n`
|
} ${this.recipe.yield.unit.toLowerCase()}\n\n`
|
||||||
this.recipe.ingredients.forEach((e) => {
|
this.recipe.ingredients.forEach((e) => {
|
||||||
ingredients += `- ${this.roundedQuantity(e.quantity)} ${e.unit} ${
|
ingredients += `- ${this.roundedQuantity(e.quantity)} ${e.unit} ${
|
||||||
e.item
|
e.item
|
||||||
|
@ -417,7 +569,7 @@ export default {
|
||||||
if (this.recipe.instructions.length) {
|
if (this.recipe.instructions.length) {
|
||||||
let instructions = `\n\nInstructions:\n\n`
|
let instructions = `\n\nInstructions:\n\n`
|
||||||
this.recipe.instructions.forEach((e, i) => {
|
this.recipe.instructions.forEach((e, i) => {
|
||||||
instructions += `${i + 1}. ${e}\n\n`
|
instructions += `Step ${i + 1}: ${e}\n\n`
|
||||||
})
|
})
|
||||||
shareContent += instructions
|
shareContent += instructions
|
||||||
}
|
}
|
||||||
|
@ -445,12 +597,13 @@ export default {
|
||||||
"How would you like to share this recipe?"
|
"How would you like to share this recipe?"
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
toggle(key) {
|
toggle(key, setDate) {
|
||||||
this.toggleStateAction({
|
this.toggleStateAction({
|
||||||
index: this.recipeIndex,
|
index: this.recipeIndex,
|
||||||
id: this.recipeID,
|
id: this.recipeID,
|
||||||
recipe: this.recipe,
|
recipe: this.recipe,
|
||||||
key,
|
key,
|
||||||
|
setDate,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
toggleFavorite() {
|
toggleFavorite() {
|
||||||
|
@ -471,14 +624,14 @@ export default {
|
||||||
this.toggle("tried")
|
this.toggle("tried")
|
||||||
},
|
},
|
||||||
recipeTried() {
|
recipeTried() {
|
||||||
this.toggle("tried")
|
this.toggle("tried", true)
|
||||||
this.$navigateBack()
|
this.$navigateBack()
|
||||||
},
|
},
|
||||||
getTime(time) {
|
formattedTime(time) {
|
||||||
let t = time.split(":")
|
let t = time.split(":")
|
||||||
let h = t[0]
|
let h = parseInt(t[0])
|
||||||
let m = t[1]
|
let m = parseInt(t[1])
|
||||||
return h !== "00" ? `${h}h ${m}m` : `${m}m`
|
return h ? (m ? `${h}h ${m}m` : `${h}h`) : `${m}m`
|
||||||
},
|
},
|
||||||
isValidURL(string) {
|
isValidURL(string) {
|
||||||
let pattern = new RegExp("^https?|www", "ig")
|
let pattern = new RegExp("^https?|www", "ig")
|
||||||
|
@ -499,6 +652,7 @@ export default {
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.showFab = true
|
this.showFab = true
|
||||||
|
setTimeout((e) => this.recipe.tried && this.showInfo(), 2000)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<Page>
|
<Page>
|
||||||
<StackLayout class="dialogContainer" :class="isLightMode">
|
<StackLayout class="dialogContainer" :class="isLightMode">
|
||||||
<!-- :class="isLightTheme ? 'light' : 'dark'" -->
|
|
||||||
<Label class="dialogTitle orkm" :text="title" />
|
<Label class="dialogTitle orkm" :text="title" />
|
||||||
<ListView
|
<ListView
|
||||||
width="100%"
|
width="100%"
|
||||||
|
@ -11,22 +10,20 @@
|
||||||
separatorColor="transparent"
|
separatorColor="transparent"
|
||||||
>
|
>
|
||||||
<v-template>
|
<v-template>
|
||||||
<StackLayout class="actionItem">
|
<Label class="actionItem" :text="item" />
|
||||||
<Label :text="item" />
|
|
||||||
</StackLayout>
|
|
||||||
</v-template>
|
</v-template>
|
||||||
</ListView>
|
</ListView>
|
||||||
<GridLayout rows="auto" columns="auto, *, auto">
|
<GridLayout rows="auto" columns="auto, *, auto" class="actionsContainer">
|
||||||
<Label
|
<Label
|
||||||
v-if="action"
|
v-if="action"
|
||||||
col="0"
|
col="0"
|
||||||
class="cancel orkm pull-left"
|
class="action orkm pull-left"
|
||||||
:text="action"
|
:text="action"
|
||||||
@tap="$modal.close(action)"
|
@tap="$modal.close(action)"
|
||||||
/>
|
/>
|
||||||
<Label
|
<Label
|
||||||
col="2"
|
col="2"
|
||||||
class="cancel orkm pull-right"
|
class="action orkm pull-right"
|
||||||
text="CANCEL"
|
text="CANCEL"
|
||||||
@tap="$modal.close(false)"
|
@tap="$modal.close(false)"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -2,23 +2,30 @@
|
||||||
<Page>
|
<Page>
|
||||||
<StackLayout class="dialogContainer" :class="isLightMode">
|
<StackLayout class="dialogContainer" :class="isLightMode">
|
||||||
<Label class="dialogTitle orkm" :text="title" />
|
<Label class="dialogTitle orkm" :text="title" />
|
||||||
<Label v-if="description" class="dialogDescription" :text="description" textWrap="true" />
|
<Label
|
||||||
<StackLayout
|
v-if="description"
|
||||||
orientation="horizontal"
|
class="dialogDescription"
|
||||||
|
:text="description"
|
||||||
|
textWrap="true"
|
||||||
|
/>
|
||||||
|
<GridLayout
|
||||||
|
rows="auto"
|
||||||
|
columns="*, auto, 32, auto"
|
||||||
class="actionsContainer"
|
class="actionsContainer"
|
||||||
horizontalAlignment="right"
|
|
||||||
>
|
>
|
||||||
<Label
|
<Label
|
||||||
|
col="1"
|
||||||
class="action orkm"
|
class="action orkm"
|
||||||
:text="cancelButtonText"
|
:text="cancelButtonText"
|
||||||
@tap="$modal.close(false)"
|
@tap="$modal.close(false)"
|
||||||
/>
|
/>
|
||||||
<Label
|
<Label
|
||||||
|
col="3"
|
||||||
class="action orkm"
|
class="action orkm"
|
||||||
:text="okButtonText"
|
:text="okButtonText"
|
||||||
@tap="$modal.close(true)"
|
@tap="$modal.close(true)"
|
||||||
/>
|
/>
|
||||||
</StackLayout>
|
</GridLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|
132
app/components/modal/ListPicker.vue
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
<template>
|
||||||
|
<Page>
|
||||||
|
<StackLayout class="dialogContainer" :class="isLightMode">
|
||||||
|
<Label class="dialogTitle orkm" :text="title" />
|
||||||
|
<StackLayout
|
||||||
|
class="dialogListPicker"
|
||||||
|
orientation="horizontal"
|
||||||
|
horizontalAlignment="center"
|
||||||
|
>
|
||||||
|
<ListPicker
|
||||||
|
ref="hrPicker"
|
||||||
|
:items="hrs"
|
||||||
|
:selectedIndex="hrIndex"
|
||||||
|
@selectedIndexChange="setHrs"
|
||||||
|
></ListPicker>
|
||||||
|
<Label
|
||||||
|
verticalAlignment="center"
|
||||||
|
class="okrb"
|
||||||
|
text=":"
|
||||||
|
textWrap="false"
|
||||||
|
/>
|
||||||
|
<ListPicker
|
||||||
|
ref="minPicker"
|
||||||
|
:items="mins"
|
||||||
|
:selectedIndex="minIndex"
|
||||||
|
@selectedIndexChange="setMins"
|
||||||
|
></ListPicker>
|
||||||
|
</StackLayout>
|
||||||
|
<GridLayout
|
||||||
|
rows="auto"
|
||||||
|
columns="*, auto, 32, auto"
|
||||||
|
class="actionsContainer"
|
||||||
|
>
|
||||||
|
<Label
|
||||||
|
col="1"
|
||||||
|
class="action orkm"
|
||||||
|
text="CANCEL"
|
||||||
|
@tap="$modal.close(false)"
|
||||||
|
/>
|
||||||
|
<Label
|
||||||
|
col="3"
|
||||||
|
class="action orkm"
|
||||||
|
:text="action"
|
||||||
|
@tap="$modal.close(selectedTime)"
|
||||||
|
/>
|
||||||
|
</GridLayout>
|
||||||
|
</StackLayout>
|
||||||
|
</Page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { Application } from "@nativescript/core"
|
||||||
|
export default {
|
||||||
|
props: ["title", "selectedHr", "selectedMin", "action"],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
hrs: [
|
||||||
|
"00",
|
||||||
|
"01",
|
||||||
|
"02",
|
||||||
|
"03",
|
||||||
|
"04",
|
||||||
|
"05",
|
||||||
|
"06",
|
||||||
|
"07",
|
||||||
|
"08",
|
||||||
|
"09",
|
||||||
|
"10",
|
||||||
|
"11",
|
||||||
|
"12",
|
||||||
|
"13",
|
||||||
|
"14",
|
||||||
|
"15",
|
||||||
|
"16",
|
||||||
|
"17",
|
||||||
|
"18",
|
||||||
|
"19",
|
||||||
|
"20",
|
||||||
|
"21",
|
||||||
|
"22",
|
||||||
|
"23",
|
||||||
|
],
|
||||||
|
mins: [
|
||||||
|
"00",
|
||||||
|
"01",
|
||||||
|
"02",
|
||||||
|
"03",
|
||||||
|
"04",
|
||||||
|
"05",
|
||||||
|
"06",
|
||||||
|
"07",
|
||||||
|
"08",
|
||||||
|
"09",
|
||||||
|
"10",
|
||||||
|
"15",
|
||||||
|
"20",
|
||||||
|
"25",
|
||||||
|
"30",
|
||||||
|
"35",
|
||||||
|
"40",
|
||||||
|
"45",
|
||||||
|
"50",
|
||||||
|
"55",
|
||||||
|
],
|
||||||
|
selectedHrs: "00",
|
||||||
|
selectedMins: "00",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
hrIndex() {
|
||||||
|
return this.hrs.indexOf(this.selectedHr)
|
||||||
|
},
|
||||||
|
minIndex() {
|
||||||
|
return this.mins.indexOf(this.selectedMin)
|
||||||
|
},
|
||||||
|
isLightMode() {
|
||||||
|
return Application.systemAppearance()
|
||||||
|
},
|
||||||
|
selectedTime() {
|
||||||
|
return this.selectedHrs + ":" + this.selectedMins
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setHrs(args) {
|
||||||
|
this.selectedHrs = this.hrs[args.object.selectedIndex]
|
||||||
|
},
|
||||||
|
setMins(args) {
|
||||||
|
this.selectedMins = this.mins[args.object.selectedIndex]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -2,27 +2,38 @@
|
||||||
<Page>
|
<Page>
|
||||||
<StackLayout class="dialogContainer" :class="isLightMode">
|
<StackLayout class="dialogContainer" :class="isLightMode">
|
||||||
<Label class="dialogTitle orkm" :text="title" />
|
<Label class="dialogTitle orkm" :text="title" />
|
||||||
<StackLayout class="dialogInputField">
|
<StackLayout class="dialogInput">
|
||||||
<TextField
|
<TextField
|
||||||
|
@loaded="focusField"
|
||||||
:hint="hint"
|
:hint="hint"
|
||||||
v-model="category"
|
v-model="category"
|
||||||
autocapitalizationType="words"
|
autocapitalizationType="words"
|
||||||
/>
|
/>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<StackLayout orientation="horizontal" horizontalAlignment="right">
|
<GridLayout
|
||||||
<Label class="action orkm" text="CANCEL" @tap="$modal.close(false)" />
|
rows="auto"
|
||||||
|
columns="*, auto, 32, auto"
|
||||||
|
class="actionsContainer"
|
||||||
|
>
|
||||||
<Label
|
<Label
|
||||||
|
col="1"
|
||||||
|
class="action orkm"
|
||||||
|
text="CANCEL"
|
||||||
|
@tap="$modal.close(false)"
|
||||||
|
/>
|
||||||
|
<Label
|
||||||
|
col="3"
|
||||||
class="action orkm"
|
class="action orkm"
|
||||||
:text="action"
|
:text="action"
|
||||||
@tap="$modal.close(category)"
|
@tap="$modal.close(category)"
|
||||||
/>
|
/>
|
||||||
</StackLayout>
|
</GridLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { Application } from "@nativescript/core"
|
import { Application, Utils } from "@nativescript/core"
|
||||||
export default {
|
export default {
|
||||||
props: ["title", "hint", "action"],
|
props: ["title", "hint", "action"],
|
||||||
data() {
|
data() {
|
||||||
|
@ -35,5 +46,11 @@ export default {
|
||||||
return Application.systemAppearance()
|
return Application.systemAppearance()
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
methods: {
|
||||||
|
focusField(args) {
|
||||||
|
args.object.focus()
|
||||||
|
setTimeout((e) => Utils.ad.showSoftInput(args.object.android), 1)
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
12
app/main.js
|
@ -12,11 +12,13 @@ Vue.registerElement(
|
||||||
"RadSideDrawer",
|
"RadSideDrawer",
|
||||||
() => require("nativescript-ui-sidedrawer").RadSideDrawer
|
() => require("nativescript-ui-sidedrawer").RadSideDrawer
|
||||||
)
|
)
|
||||||
|
import { CheckBox } from "@nstudio/nativescript-checkbox"
|
||||||
// Vue.registerElement(
|
Vue.registerElement("CheckBox", () => CheckBox, {
|
||||||
// 'Fab',
|
model: {
|
||||||
// () => require('@nstudio/nativescript-floatingactionbutton').Fab
|
prop: "checked",
|
||||||
// );
|
event: "checkedChange",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
if (TNS_ENV !== "production") {
|
if (TNS_ENV !== "production") {
|
||||||
// Vue.use(VueDevtools)
|
// Vue.use(VueDevtools)
|
||||||
|
|
365
app/store.js
|
@ -2,124 +2,182 @@ import Vue from "vue"
|
||||||
import Vuex from "vuex"
|
import Vuex from "vuex"
|
||||||
import { Couchbase } from "nativescript-couchbase-plugin"
|
import { Couchbase } from "nativescript-couchbase-plugin"
|
||||||
const recipesDB = new Couchbase("enrecipes")
|
const recipesDB = new Couchbase("enrecipes")
|
||||||
const categoriesDB = new Couchbase("categories")
|
const categoriesDB = new Couchbase("userCategories")
|
||||||
|
const yieldUnitsDB = new Couchbase("userYieldUnits")
|
||||||
|
|
||||||
Vue.use(Vuex)
|
Vue.use(Vuex)
|
||||||
|
|
||||||
|
let defaultCategories = [
|
||||||
|
"Appetizers",
|
||||||
|
"BBQ",
|
||||||
|
"Beverages",
|
||||||
|
"Breads",
|
||||||
|
"Breakfast",
|
||||||
|
"Desserts",
|
||||||
|
"Dinner",
|
||||||
|
"Drinks",
|
||||||
|
"Healthy",
|
||||||
|
"Lunch",
|
||||||
|
"Main dishes",
|
||||||
|
"Meat",
|
||||||
|
"Noodles",
|
||||||
|
"Pasta",
|
||||||
|
"Poultry",
|
||||||
|
"Rice",
|
||||||
|
"Salads",
|
||||||
|
"Sauces",
|
||||||
|
"Seafood",
|
||||||
|
"Side dishes",
|
||||||
|
"Snacks",
|
||||||
|
"Soups",
|
||||||
|
"Undefined",
|
||||||
|
"Vegan",
|
||||||
|
"Vegetarian",
|
||||||
|
]
|
||||||
|
let defaultYieldUnits = [
|
||||||
|
"Serving",
|
||||||
|
"Piece",
|
||||||
|
"Teaspoon",
|
||||||
|
"Tablespoon",
|
||||||
|
"Fluid Ounce",
|
||||||
|
"Ounce",
|
||||||
|
"Pound",
|
||||||
|
"Gram",
|
||||||
|
"Kilogram",
|
||||||
|
"Cup",
|
||||||
|
"Gallon",
|
||||||
|
"Millilitre",
|
||||||
|
"Litre",
|
||||||
|
"Roll",
|
||||||
|
"Pattie",
|
||||||
|
"Loaf",
|
||||||
|
]
|
||||||
|
|
||||||
export default new Vuex.Store({
|
export default new Vuex.Store({
|
||||||
state: {
|
state: {
|
||||||
recipes: [
|
recipes: [
|
||||||
{
|
// {
|
||||||
imageSrc: null,
|
// imageSrc: null,
|
||||||
title: "Mushroom & Spinach Risotto",
|
// title: "Mushroom & Spinach Risotto",
|
||||||
category: "Lunch",
|
// category: "Lunch",
|
||||||
prepTime: "00:25",
|
// timeRequired: "01:45",
|
||||||
cookTime: "00:45",
|
// yield: {
|
||||||
portionSize: "8",
|
// quantity: 1,
|
||||||
ingredients: [
|
// unit: "Serving",
|
||||||
{
|
// },
|
||||||
item: "reduced-sodium chicken broth",
|
// ingredients: [
|
||||||
unit: "cup",
|
// {
|
||||||
quantity: "5.25",
|
// item: "reduced-sodium chicken broth",
|
||||||
},
|
// unit: "cup",
|
||||||
{ item: "sliced fresh mushrooms", unit: "cup", quantity: "2.5" },
|
// quantity: "5.25",
|
||||||
{ item: "medium onion, finely chopped", unit: "unit", quantity: "1" },
|
// },
|
||||||
{ item: "butter", unit: "Tbsp", quantity: "3" },
|
// { item: "sliced fresh mushrooms", unit: "cup", quantity: "2.5" },
|
||||||
{ item: "Garlic", unit: "unit", quantity: "3" },
|
// { item: "medium onion, finely chopped", unit: "unit", quantity: "1" },
|
||||||
{
|
// { item: "butter", unit: "Tbsp", quantity: "3" },
|
||||||
item: "white wine or reduced-sodium chicken broth",
|
// { item: "Garlic", unit: "unit", quantity: "3" },
|
||||||
unit: "cup",
|
// {
|
||||||
quantity: ".75",
|
// item: "white wine or reduced-sodium chicken broth",
|
||||||
},
|
// unit: "l",
|
||||||
{ item: "heavy whipping cream", unit: "cup", quantity: "1" },
|
// quantity: ".75",
|
||||||
{ item: "uncooked arborio rice", unit: "cup", quantity: "1.75" },
|
// },
|
||||||
{ item: "olive oil", unit: "Tbsp", quantity: "2" },
|
// { item: "heavy whipping cream", unit: "cup", quantity: "1" },
|
||||||
{
|
// { item: "uncooked arborio rice", unit: "cup", quantity: "1.75" },
|
||||||
item: "frozen chopped spinach, thawed and squeezed dry",
|
// { item: "olive oil", unit: "Tbsp", quantity: "2" },
|
||||||
unit: "cup",
|
// {
|
||||||
quantity: "1.5",
|
// item: "frozen chopped spinach, thawed and squeezed dry",
|
||||||
},
|
// unit: "cup",
|
||||||
{ item: "pepper", unit: "tsp", quantity: ".5" },
|
// quantity: "1.5",
|
||||||
{ item: "Salt", unit: "tsp", quantity: ".25" },
|
// },
|
||||||
{ item: "grated Parmesan cheese", unit: "cup", quantity: "1" },
|
// { item: "pepper", unit: "tsp", quantity: ".5" },
|
||||||
],
|
// { item: "Salt", unit: "tsp", quantity: ".25" },
|
||||||
instructions: [
|
// { item: "grated Parmesan cheese", unit: "cup", quantity: "1" },
|
||||||
"In a large saucepan, heat broth and keep warm. In a large skillet, saute mushrooms and onion in butter until tender. Add garlic; cook 1 minute longer. Stir in wine. Bring to a boil; cook until liquid is reduced by half. Add cream; cook and stir over medium heat until slightly thickened",
|
// ],
|
||||||
"In a large saucepan, saute rice in oil for 2-3 minutes or until rice is lightly browned. Stir in 1/2 cup hot broth. Reduce heat; cook and stir for 20 minutes or until broth is absorbed.",
|
// instructions: [
|
||||||
"Continue adding hot broth, 1/2 cup at a time, and stirring until all the broth has been absorbed and rice is tender but firm. Add the mushroom mixture, spinach, pepper, salt and grated Parmesan cheese; cook and stir until heated through. If desired, sprinkle with parsley and shaved Parmesan cheese. Serve immediately.",
|
// "In a large saucepan, heat broth and keep warm. In a large skillet, saute mushrooms and onion in butter until tender. Add garlic; cook 1 minute longer. Stir in wine. Bring to a boil; cook until liquid is reduced by half. Add cream; cook and stir over medium heat until slightly thickened",
|
||||||
],
|
// "In a large saucepan, saute rice in oil for 2-3 minutes or until rice is lightly browned. Stir in 1/2 cup hot broth. Reduce heat; cook and stir for 20 minutes or until broth is absorbed.",
|
||||||
notes: [
|
// "Continue adding hot broth, 1/2 cup at a time, and stirring until all the broth has been absorbed and rice is tender but firm. Add the mushroom mixture, spinach, pepper, salt and grated Parmesan cheese; cook and stir until heated through. If desired, sprinkle with parsley and shaved Parmesan cheese. Serve immediately.",
|
||||||
"Nutrition Facts\n3/4 cup: 409 calories, 22g fat (12g saturated fat), 61mg cholesterol, 667mg sodium, 41g carbohydrate (3g sugars, 2g fiber), 11g protein.",
|
// ],
|
||||||
],
|
// notes: [
|
||||||
references: [
|
// "Nutrition Facts\n3/4 cup: 409 calories, 22g fat (12g saturated fat), 61mg cholesterol, 667mg sodium, 41g carbohydrate (3g sugars, 2g fiber), 11g protein.",
|
||||||
"https://www.tasteofhome.com/recipes/mushroom-spinach-risotto/",
|
// ],
|
||||||
],
|
// references: [
|
||||||
isFavorite: false,
|
// "https://www.tasteofhome.com/recipes/mushroom-spinach-risotto/",
|
||||||
tried: true,
|
// ],
|
||||||
triedOn: "2020-10-28T18:19:06.528Z",
|
// isFavorite: false,
|
||||||
lastModified: "2020-10-28T06:19:06.528Z",
|
// tried: false,
|
||||||
id: "57qm8oqxdr",
|
// lastTried: "2020-10-28T18:19:06.528Z",
|
||||||
},
|
// lastModified: "2020-10-28T06:19:06.528Z",
|
||||||
|
// id: "57qm8oqxdr",
|
||||||
|
// },
|
||||||
],
|
],
|
||||||
categories: [],
|
categories: [],
|
||||||
|
userCategories: [],
|
||||||
units: [
|
units: [
|
||||||
"unit",
|
"unit",
|
||||||
"tsp",
|
"tsp",
|
||||||
"Tbsp",
|
"tbsp",
|
||||||
"oz",
|
"fl oz",
|
||||||
"cup",
|
"cup",
|
||||||
"pt",
|
"pt",
|
||||||
"qt",
|
"qt",
|
||||||
"lb",
|
|
||||||
"gal",
|
"gal",
|
||||||
"ml",
|
"ml",
|
||||||
"L",
|
"l",
|
||||||
|
"oz",
|
||||||
|
"lb",
|
||||||
"mg",
|
"mg",
|
||||||
"g",
|
"g",
|
||||||
"kg",
|
"kg",
|
||||||
"mm",
|
|
||||||
"cm",
|
"cm",
|
||||||
"m",
|
|
||||||
"in",
|
"in",
|
||||||
"°C",
|
"clove",
|
||||||
"°F",
|
"pinch",
|
||||||
|
"drop",
|
||||||
|
"dozen",
|
||||||
|
"stick",
|
||||||
|
"small",
|
||||||
|
"medium",
|
||||||
|
"large",
|
||||||
],
|
],
|
||||||
|
yieldUnits: [],
|
||||||
|
userYieldUnits: [],
|
||||||
icon: {
|
icon: {
|
||||||
home: "\ued99",
|
home: "\ued3b",
|
||||||
heart: "\ued94",
|
heart: "\ued36",
|
||||||
heartOutline: "\uead6",
|
heartOutline: "\uea6c",
|
||||||
label: "\uedaf",
|
label: "\ued51",
|
||||||
cog: "\ued05",
|
cog: "\ueca6",
|
||||||
info: "\ueda7",
|
info: "\ued49",
|
||||||
menu: "\ueb2a",
|
menu: "\ueac1",
|
||||||
search: "\uebbc",
|
search: "\ueb54",
|
||||||
sort: "\ueb2b",
|
sort: "\ueac2",
|
||||||
plus: "\ueb89",
|
plus: "\ueb21",
|
||||||
close: "\uec4e",
|
plusCircle: "\ueb22",
|
||||||
image: "\ueae9",
|
close: "\uebe9",
|
||||||
addImage: "\ueae8",
|
image: "\uea7f",
|
||||||
back: "\ue988",
|
food: "\ueb3e",
|
||||||
save: "\uee48",
|
back: "\uea95",
|
||||||
camera: "\uecc2",
|
save: "\uedeb",
|
||||||
share: "\uee50",
|
camera: "\uec61",
|
||||||
edit: "\uee17",
|
share: "\uedf3",
|
||||||
theme: "\ued09",
|
edit: "\uedba",
|
||||||
folder: "\ued7c",
|
theme: "\uecaa",
|
||||||
backup: "\uee48",
|
restore: "\uea72",
|
||||||
restore: "\ueadc",
|
link: "\ueaa0",
|
||||||
link: "\ueb09",
|
file: "\ued02",
|
||||||
file: "\ued60",
|
user: "\uee33",
|
||||||
user: "\uee8e",
|
trash: "\uee26",
|
||||||
trash: "\uee83",
|
donate: "\ueb4f",
|
||||||
donate: "\ued41",
|
trylater: "\uec31",
|
||||||
trylater: "\uec96",
|
trylaterOutline: "\ue94a",
|
||||||
trylaterOutline: "\ue9bb",
|
note: "\ueb04",
|
||||||
note: "\uee0a",
|
copy: "\ue9e6",
|
||||||
copy: "\uea51",
|
check: "\ue9ab",
|
||||||
plusCircle: "\ueb8a",
|
telegram: "\ueec7",
|
||||||
unchecked: "\uea16",
|
time: "\ueba2",
|
||||||
checked: "\uece6",
|
item: "\ue99d",
|
||||||
telegram: "\ue95e",
|
step: "\ue948",
|
||||||
|
source: "\ueaa0",
|
||||||
},
|
},
|
||||||
currentComponent: "EnRecipes",
|
currentComponent: "EnRecipes",
|
||||||
},
|
},
|
||||||
|
@ -132,58 +190,58 @@ export default new Vuex.Store({
|
||||||
},
|
},
|
||||||
initializeCategories(state) {
|
initializeCategories(state) {
|
||||||
let isCategoriesStored = categoriesDB.query({ select: [] }).length
|
let isCategoriesStored = categoriesDB.query({ select: [] }).length
|
||||||
let cats
|
|
||||||
if (isCategoriesStored) {
|
if (isCategoriesStored) {
|
||||||
cats = categoriesDB.getDocument("categories").categories
|
state.userCategories = categoriesDB.getDocument(
|
||||||
} else {
|
"userCategories"
|
||||||
categoriesDB.createDocument(
|
).userCategories
|
||||||
{
|
let categoriesWithRecipes = state.recipes.map((e) => e.category)
|
||||||
categories: [
|
state.userCategories = state.userCategories.filter((e) =>
|
||||||
"Appetizers",
|
categoriesWithRecipes.includes(e)
|
||||||
"BBQ",
|
|
||||||
"Beverages",
|
|
||||||
"Breads",
|
|
||||||
"Breakfast",
|
|
||||||
"Desserts",
|
|
||||||
"Dinner",
|
|
||||||
"Drinks",
|
|
||||||
"Healthy",
|
|
||||||
"Lunch",
|
|
||||||
"Main dishes",
|
|
||||||
"Meat",
|
|
||||||
"Noodles",
|
|
||||||
"Pasta",
|
|
||||||
"Poultry",
|
|
||||||
"Rice",
|
|
||||||
"Salads",
|
|
||||||
"Sauces",
|
|
||||||
"Seafood",
|
|
||||||
"Side dishes",
|
|
||||||
"Snacks",
|
|
||||||
"Soups",
|
|
||||||
"Undefined",
|
|
||||||
"Vegan",
|
|
||||||
"Vegetarian",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"categories"
|
|
||||||
)
|
)
|
||||||
cats = categoriesDB.getDocument("categories").categories
|
} else {
|
||||||
|
categoriesDB.createDocument({ userCategories: [] }, "userCategories")
|
||||||
}
|
}
|
||||||
cats.forEach((e) => state.categories.push(e))
|
state.categories = [...defaultCategories, ...state.userCategories]
|
||||||
|
state.categories.sort()
|
||||||
|
},
|
||||||
|
initializeYieldUnits(state) {
|
||||||
|
let isYieldUnitsStored = yieldUnitsDB.query({ select: [] }).length
|
||||||
|
if (isYieldUnitsStored) {
|
||||||
|
state.userYieldUnits = yieldUnitsDB.getDocument(
|
||||||
|
"userYieldUnits"
|
||||||
|
).userYieldUnits
|
||||||
|
let yieldUnitsWithRecipes = state.recipes.map((e) => e.yield.unit)
|
||||||
|
state.userYieldUnits = state.userYieldUnits.filter((e) =>
|
||||||
|
yieldUnitsWithRecipes.includes(e)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
yieldUnitsDB.createDocument({ userYieldUnits: [] }, "userYieldUnits")
|
||||||
|
}
|
||||||
|
state.yieldUnits = [...defaultYieldUnits, ...state.userYieldUnits]
|
||||||
},
|
},
|
||||||
addRecipe(state, { id, recipe }) {
|
addRecipe(state, { id, recipe }) {
|
||||||
state.recipes.push(recipe)
|
state.recipes.push(recipe)
|
||||||
recipesDB.createDocument(recipe, id)
|
recipesDB.createDocument(recipe, id)
|
||||||
},
|
},
|
||||||
addCategory(state, category) {
|
addCategory(state, category) {
|
||||||
let a = state.categories.filter((e) => e === category).length
|
let lowercase = state.categories.map((e) => e.toLowerCase())
|
||||||
if (a == 0) {
|
if (lowercase.indexOf(category.toLowerCase()) == -1) {
|
||||||
state.categories.push(category)
|
state.userCategories.push(category)
|
||||||
state.categories.sort()
|
categoriesDB.updateDocument("userCategories", {
|
||||||
categoriesDB.updateDocument("categories", {
|
userCategories: [...state.userCategories],
|
||||||
categories: [...state.categories],
|
|
||||||
})
|
})
|
||||||
|
state.categories = [...defaultCategories, ...state.userCategories]
|
||||||
|
state.categories.sort()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
addYieldUnit(state, unit) {
|
||||||
|
let lowercase = state.yieldUnits.map((e) => e.toLowerCase())
|
||||||
|
if (lowercase.indexOf(unit.toLowerCase()) == -1) {
|
||||||
|
state.userYieldUnits.push(unit)
|
||||||
|
yieldUnitsDB.updateDocument("userYieldUnits", {
|
||||||
|
userYieldUnits: [...state.userYieldUnits],
|
||||||
|
})
|
||||||
|
state.yieldUnits = [...defaultYieldUnits, ...state.userYieldUnits]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
overwriteRecipe(state, { index, id, recipe }) {
|
overwriteRecipe(state, { index, id, recipe }) {
|
||||||
|
@ -194,25 +252,27 @@ export default new Vuex.Store({
|
||||||
state.recipes.splice(index, 1)
|
state.recipes.splice(index, 1)
|
||||||
recipesDB.deleteDocument(id)
|
recipesDB.deleteDocument(id)
|
||||||
},
|
},
|
||||||
toggleState(state, { index, id, recipe, key }) {
|
toggleState(state, { index, id, recipe, key, setDate }) {
|
||||||
state.recipes[index][key] = !state.recipes[index][key]
|
state.recipes[index][key] = !state.recipes[index][key]
|
||||||
|
if (setDate) state.recipes[index].lastTried = new Date()
|
||||||
recipesDB.updateDocument(id, recipe)
|
recipesDB.updateDocument(id, recipe)
|
||||||
},
|
},
|
||||||
|
setLastTriedDate(state, index) {
|
||||||
|
state.recipes[index].lastTried = new Date()
|
||||||
|
recipesDB.updateDocument(state.recipes[index].id, state.recipes[index])
|
||||||
|
},
|
||||||
setCurrentComponent(state, comp) {
|
setCurrentComponent(state, comp) {
|
||||||
state.currentComponent = comp
|
state.currentComponent = comp
|
||||||
},
|
},
|
||||||
renameCategory(state, { current, updated }) {
|
renameCategory(state, { current, updated }) {
|
||||||
let exists = state.categories.filter((e) => e === updated).length
|
let lowercase = state.categories.map((e) => e.toLowerCase())
|
||||||
|
if (lowercase.indexOf(updated.toLowerCase()) == -1) {
|
||||||
state.categories.splice(state.categories.indexOf(current), 1)
|
state.userCategories.push(updated)
|
||||||
|
categoriesDB.updateDocument("userCategories", {
|
||||||
// update recipes with updated category
|
userCategories: [...state.userCategories],
|
||||||
if (!exists) {
|
|
||||||
state.categories.push(updated)
|
|
||||||
state.categories.sort()
|
|
||||||
categoriesDB.updateDocument("categories", {
|
|
||||||
categories: [...state.categories],
|
|
||||||
})
|
})
|
||||||
|
state.categories = [...defaultCategories, ...state.userCategories]
|
||||||
|
state.categories.sort()
|
||||||
}
|
}
|
||||||
state.recipes.forEach((e, i) => {
|
state.recipes.forEach((e, i) => {
|
||||||
if (e.category == current) {
|
if (e.category == current) {
|
||||||
|
@ -231,12 +291,18 @@ export default new Vuex.Store({
|
||||||
initializeCategories({ commit }) {
|
initializeCategories({ commit }) {
|
||||||
commit("initializeCategories")
|
commit("initializeCategories")
|
||||||
},
|
},
|
||||||
|
initializeYieldUnits({ commit }) {
|
||||||
|
commit("initializeYieldUnits")
|
||||||
|
},
|
||||||
addRecipeAction({ commit }, recipe) {
|
addRecipeAction({ commit }, recipe) {
|
||||||
commit("addRecipe", recipe)
|
commit("addRecipe", recipe)
|
||||||
},
|
},
|
||||||
addCategoryAction({ commit }, category) {
|
addCategoryAction({ commit }, category) {
|
||||||
commit("addCategory", category)
|
commit("addCategory", category)
|
||||||
},
|
},
|
||||||
|
addYieldUnitAction({ commit }, yieldUnit) {
|
||||||
|
commit("addYieldUnit", yieldUnit)
|
||||||
|
},
|
||||||
overwriteRecipeAction({ commit }, updatedRecipe) {
|
overwriteRecipeAction({ commit }, updatedRecipe) {
|
||||||
commit("overwriteRecipe", updatedRecipe)
|
commit("overwriteRecipe", updatedRecipe)
|
||||||
},
|
},
|
||||||
|
@ -246,6 +312,9 @@ export default new Vuex.Store({
|
||||||
toggleStateAction({ commit }, toggledRecipe) {
|
toggleStateAction({ commit }, toggledRecipe) {
|
||||||
commit("toggleState", toggledRecipe)
|
commit("toggleState", toggledRecipe)
|
||||||
},
|
},
|
||||||
|
setLastTriedDateAction({ commit }, index) {
|
||||||
|
commit("setLastTriedDate", index)
|
||||||
|
},
|
||||||
setCurrentComponentAction({ commit }, comp) {
|
setCurrentComponentAction({ commit }, comp) {
|
||||||
commit("setCurrentComponent", comp)
|
commit("setCurrentComponent", comp)
|
||||||
},
|
},
|
||||||
|
|
22
app/worker.service.js
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
const workers = []
|
||||||
|
|
||||||
|
export class WorkerService {
|
||||||
|
constructor() {}
|
||||||
|
initImageProcessor() {
|
||||||
|
if (this.imageProcessor) {
|
||||||
|
return this.imageProcessor
|
||||||
|
}
|
||||||
|
const ImageProcessor = require("nativescript-worker-loader!./workers/ImageProcessor.worker.js")
|
||||||
|
this.imageProcessor = new ImageProcessor()
|
||||||
|
workers.push(this.imageProcessor)
|
||||||
|
return this.imageProcessor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (module.hot) {
|
||||||
|
module.hot.dispose(() => {
|
||||||
|
workers.forEach((w) => {
|
||||||
|
w.terminate()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
12
app/workers/ImageProcessor.worker.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
require("tns-core-modules/globals")
|
||||||
|
import { ImageSource } from "@nativescript/core"
|
||||||
|
|
||||||
|
global.onmessage = function({ data }) {
|
||||||
|
let imgFile = data.imgFile
|
||||||
|
let imgSavedToPath = data.imgSavedToPath
|
||||||
|
ImageSource.fromFile(imgFile).then((imgData) => {
|
||||||
|
if (imgData.saveToFile(imgSavedToPath, "jpg")) {
|
||||||
|
global.postMessage("savedToFile")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
|
@ -1,11 +1,12 @@
|
||||||
import { NativeScriptConfig } from '@nativescript/core'
|
import { NativeScriptConfig } from "@nativescript/core"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
id: 'com.vishnuraghav.enrecipes',
|
id: "com.vishnuraghav.enrecipes",
|
||||||
appResourcesPath: 'app/App_Resources',
|
appResourcesPath: "App_Resources",
|
||||||
android: {
|
android: {
|
||||||
v8Flags: '--expose_gc',
|
v8Flags: "--expose_gc",
|
||||||
markingMode: 'none',
|
markingMode: "none",
|
||||||
|
codeCache: true,
|
||||||
},
|
},
|
||||||
appPath: 'app',
|
appPath: "app",
|
||||||
} as NativeScriptConfig
|
} as NativeScriptConfig
|
||||||
|
|
5
package-lock.json
generated
|
@ -1203,6 +1203,11 @@
|
||||||
"mkdirp": "^1.0.4"
|
"mkdirp": "^1.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@nstudio/nativescript-checkbox": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@nstudio/nativescript-checkbox/-/nativescript-checkbox-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-ypIGAHxDE/2o3CzYohSdypdhiw4GjMcZ3H/qtF4z97HMcMqj+g5bYPDC9cRH97qgAez8jf/z3UX5OzOtnrNxug=="
|
||||||
|
},
|
||||||
"@types/anymatch": {
|
"@types/anymatch": {
|
||||||
"version": "1.3.1",
|
"version": "1.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz",
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
"@nativescript/datetimepicker": "^2.0.4",
|
"@nativescript/datetimepicker": "^2.0.4",
|
||||||
"@nativescript/theme": "^3.0.0",
|
"@nativescript/theme": "^3.0.0",
|
||||||
"@nativescript/webpack": "3.0.0",
|
"@nativescript/webpack": "3.0.0",
|
||||||
|
"@nstudio/nativescript-checkbox": "^2.0.4",
|
||||||
"nativescript-clipboard": "^2.0.0",
|
"nativescript-clipboard": "^2.0.0",
|
||||||
"nativescript-couchbase-plugin": "^0.9.6",
|
"nativescript-couchbase-plugin": "^0.9.6",
|
||||||
"nativescript-feedback": "^2.0.0",
|
"nativescript-feedback": "^2.0.0",
|
||||||
|
|