kasy-cli 1.4.2 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commands/new.js +9 -2
- package/lib/scaffold/CHANGELOG.json +5 -5
- package/lib/scaffold/features/widget/lib/core/home_widgets/home_widget_mywidget_service.dart +61 -20
- package/package.json +1 -1
- package/templates/firebase/android/app/src/main/kotlin/com/aicrus/firebase/kit/MyWidget.kt +48 -12
- package/templates/firebase/home_widget_config.json +9 -5
- package/templates/firebase/ios/HomeWidgetExtension/MyWidget.swift +69 -41
- package/templates/firebase/lib/core/home_widgets/home_widget_mywidget_service.dart +60 -19
package/lib/commands/new.js
CHANGED
|
@@ -191,9 +191,16 @@ async function promptOrganizationIfNeeded(tr, onCancel) {
|
|
|
191
191
|
|
|
192
192
|
function printBanner(tr) {
|
|
193
193
|
const bar = kleur.gray('─────────────────────────────────────────────────');
|
|
194
|
-
const
|
|
194
|
+
const logo = [
|
|
195
|
+
' ╦╔═ ╔═╗ ╔═╗ ╦ ╦',
|
|
196
|
+
' ╠╩╗ ╠═╣ ╚═╗ ╚╦╝',
|
|
197
|
+
' ╩ ╩ ╩ ╩ ╚═╝ ╩ ',
|
|
198
|
+
]
|
|
199
|
+
.map((line) => gradient(['#a78bfa', '#60a5fa'])(line))
|
|
200
|
+
.join('\n');
|
|
195
201
|
console.log(`\n${bar}\n`);
|
|
196
|
-
console.log(
|
|
202
|
+
console.log(logo);
|
|
203
|
+
console.log('');
|
|
197
204
|
console.log(` ${kleur.dim(tr('new.subtitle2'))}`);
|
|
198
205
|
console.log(`\n${bar}\n`);
|
|
199
206
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"1.
|
|
2
|
+
"1.5.0": {
|
|
3
3
|
"modules": {
|
|
4
|
-
"
|
|
5
|
-
"pt": "
|
|
6
|
-
"en": "
|
|
7
|
-
"es": "
|
|
4
|
+
"widget": {
|
|
5
|
+
"pt": "Widget redesenhado: saudação por horário no idioma do usuário (pt/en/es), nome real e status do plano",
|
|
6
|
+
"en": "Redesigned widget: time-of-day greeting in the user's language (pt/en/es), real name and plan status",
|
|
7
|
+
"es": "Widget rediseñado: saludo según el horario en el idioma del usuario (pt/en/es), nombre real y estado del plan"
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
10
|
}
|
package/lib/scaffold/features/widget/lib/core/home_widgets/home_widget_mywidget_service.dart
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import 'dart:io';
|
|
2
|
+
|
|
1
3
|
import 'package:home_widget/home_widget.dart';
|
|
2
|
-
import 'package:
|
|
4
|
+
import 'package:kasy_kit/core/data/models/user.dart';
|
|
3
5
|
import 'package:kasy_kit/core/home_widgets/home_widget_service.dart';
|
|
4
6
|
import 'package:kasy_kit/core/states/user_state_notifier.dart';
|
|
7
|
+
import 'package:logger/logger.dart';
|
|
5
8
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|
6
9
|
|
|
7
10
|
part 'home_widget_mywidget_service.g.dart';
|
|
@@ -18,40 +21,78 @@ class MyWidgetHomeWidget extends _$MyWidgetHomeWidget
|
|
|
18
21
|
@override
|
|
19
22
|
Future<void> update() {
|
|
20
23
|
Logger().i('🔄 Updating MyWidget Home Widget');
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
final
|
|
24
|
+
final user = ref.read(userStateNotifierProvider).user;
|
|
25
|
+
|
|
26
|
+
final name = switch (user) {
|
|
27
|
+
AuthenticatedUserData(:final name)
|
|
28
|
+
when name != null && name.isNotEmpty =>
|
|
29
|
+
name.split(' ').first,
|
|
30
|
+
_ => 'there',
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
final isPro = switch (user) {
|
|
34
|
+
AuthenticatedUserData(:final subscription) ||
|
|
35
|
+
AnonymousUserData(:final subscription) =>
|
|
36
|
+
subscription?.isActive ?? false,
|
|
37
|
+
_ => false,
|
|
38
|
+
};
|
|
24
39
|
|
|
25
|
-
return updateWidget({
|
|
40
|
+
return updateWidget({
|
|
41
|
+
'greeting': _greeting(),
|
|
42
|
+
'name': name,
|
|
43
|
+
'isPro': isPro.toString(),
|
|
44
|
+
});
|
|
26
45
|
}
|
|
27
46
|
|
|
28
|
-
/// Update widget data
|
|
29
|
-
///
|
|
30
|
-
/// This will save data that the widget can read
|
|
31
47
|
Future<void> updateWidget(Map<String, String> data) async {
|
|
32
|
-
await HomeWidget.saveWidgetData<String>(
|
|
48
|
+
await HomeWidget.saveWidgetData<String>(
|
|
49
|
+
'greeting', data['greeting'] ?? 'Good morning');
|
|
50
|
+
await HomeWidget.saveWidgetData<String>('name', data['name'] ?? 'there');
|
|
51
|
+
await HomeWidget.saveWidgetData<String>(
|
|
52
|
+
'isPro', data['isPro'] ?? 'false');
|
|
33
53
|
|
|
34
|
-
await HomeWidget.saveWidgetData<String>('counter', data['counter'] ?? '0');
|
|
35
|
-
|
|
36
|
-
// Trigger widget update
|
|
37
54
|
await HomeWidget.updateWidget(
|
|
38
55
|
name: _androidWidgetName,
|
|
39
56
|
iOSName: _iosWidgetName,
|
|
40
57
|
);
|
|
41
58
|
}
|
|
42
59
|
|
|
43
|
-
/// Get current widget data
|
|
44
60
|
Future<Map<String, dynamic>> getWidgetData() async {
|
|
45
61
|
return {
|
|
46
|
-
'
|
|
47
|
-
'
|
|
48
|
-
defaultValue: '
|
|
62
|
+
'greeting': await HomeWidget.getWidgetData<String>(
|
|
63
|
+
'greeting',
|
|
64
|
+
defaultValue: 'Good morning',
|
|
49
65
|
),
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
'
|
|
53
|
-
defaultValue: '0',
|
|
66
|
+
'name': await HomeWidget.getWidgetData<String>(
|
|
67
|
+
'name',
|
|
68
|
+
defaultValue: 'there',
|
|
54
69
|
),
|
|
70
|
+
'isPro': await HomeWidget.getWidgetData<String>(
|
|
71
|
+
'isPro',
|
|
72
|
+
defaultValue: 'false',
|
|
73
|
+
),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Returns a time-of-day greeting in the device language (pt / es / en).
|
|
78
|
+
// Uses Platform.localeName so it works in background isolates without
|
|
79
|
+
// requiring the Flutter locale system to be initialized.
|
|
80
|
+
static String _greeting() {
|
|
81
|
+
final lang = Platform.localeName.split(RegExp(r'[_\-]')).first.toLowerCase();
|
|
82
|
+
final hour = DateTime.now().hour;
|
|
83
|
+
|
|
84
|
+
return switch (lang) {
|
|
85
|
+
'pt' => hour < 12 ? 'Bom dia' : hour < 18 ? 'Boa tarde' : 'Boa noite',
|
|
86
|
+
'es' => hour < 12
|
|
87
|
+
? 'Buenos días'
|
|
88
|
+
: hour < 18
|
|
89
|
+
? 'Buenas tardes'
|
|
90
|
+
: 'Buenas noches',
|
|
91
|
+
_ => hour < 12
|
|
92
|
+
? 'Good morning'
|
|
93
|
+
: hour < 18
|
|
94
|
+
? 'Good afternoon'
|
|
95
|
+
: 'Good evening',
|
|
55
96
|
};
|
|
56
97
|
}
|
|
57
98
|
}
|
package/package.json
CHANGED
|
@@ -1,22 +1,29 @@
|
|
|
1
1
|
package com.aicrus.firebase.kit
|
|
2
2
|
|
|
3
|
+
import android.content.Context
|
|
3
4
|
import androidx.compose.runtime.Composable
|
|
4
5
|
import androidx.compose.ui.graphics.Color
|
|
5
6
|
import androidx.compose.ui.unit.dp
|
|
7
|
+
import androidx.compose.ui.unit.sp
|
|
6
8
|
import androidx.glance.GlanceId
|
|
7
9
|
import androidx.glance.GlanceModifier
|
|
8
10
|
import androidx.glance.appwidget.GlanceAppWidget
|
|
9
11
|
import androidx.glance.appwidget.provideContent
|
|
10
12
|
import androidx.glance.background
|
|
13
|
+
import androidx.glance.currentState
|
|
14
|
+
import androidx.glance.layout.Alignment
|
|
11
15
|
import androidx.glance.layout.Box
|
|
12
16
|
import androidx.glance.layout.Column
|
|
17
|
+
import androidx.glance.layout.Spacer
|
|
18
|
+
import androidx.glance.layout.fillMaxSize
|
|
13
19
|
import androidx.glance.layout.padding
|
|
14
20
|
import androidx.glance.state.GlanceStateDefinition
|
|
21
|
+
import androidx.glance.text.FontWeight
|
|
15
22
|
import androidx.glance.text.Text
|
|
23
|
+
import androidx.glance.text.TextStyle
|
|
24
|
+
import androidx.glance.unit.ColorProvider
|
|
16
25
|
import es.antonborri.home_widget.HomeWidgetGlanceState
|
|
17
26
|
import es.antonborri.home_widget.HomeWidgetGlanceStateDefinition
|
|
18
|
-
import android.content.Context
|
|
19
|
-
import androidx.glance.currentState
|
|
20
27
|
|
|
21
28
|
class MyWidgetWidget : GlanceAppWidget() {
|
|
22
29
|
|
|
@@ -32,18 +39,47 @@ class MyWidgetWidget : GlanceAppWidget() {
|
|
|
32
39
|
@Composable
|
|
33
40
|
private fun GlanceContent(context: Context, currentState: HomeWidgetGlanceState) {
|
|
34
41
|
val prefs = currentState.preferences
|
|
42
|
+
val greeting = prefs.getString("greeting", "Good morning") ?: "Good morning"
|
|
43
|
+
val name = prefs.getString("name", "there") ?: "there"
|
|
44
|
+
val isPro = prefs.getString("isPro", "false") == "true"
|
|
35
45
|
|
|
36
|
-
val
|
|
37
|
-
|
|
38
|
-
val
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
Column {
|
|
42
|
-
|
|
43
|
-
Text(text = title ?: "--", modifier = GlanceModifier.padding(bottom = 4.dp))
|
|
44
|
-
|
|
45
|
-
Text(text = counter ?: "--")
|
|
46
|
+
val bgColor = Color(red = 0.08f, green = 0.03f, blue = 0.16f)
|
|
47
|
+
val white = Color.White
|
|
48
|
+
val whiteSubtle = Color(red = 1f, green = 1f, blue = 1f, alpha = 0.55f)
|
|
49
|
+
val gold = Color(red = 1f, green = 0.84f, blue = 0f)
|
|
50
|
+
val whiteVerySubtle = Color(red = 1f, green = 1f, blue = 1f, alpha = 0.40f)
|
|
46
51
|
|
|
52
|
+
Box(
|
|
53
|
+
modifier = GlanceModifier.fillMaxSize().background(bgColor).padding(16.dp),
|
|
54
|
+
contentAlignment = Alignment.TopStart,
|
|
55
|
+
) {
|
|
56
|
+
Column(modifier = GlanceModifier.fillMaxSize()) {
|
|
57
|
+
Text(
|
|
58
|
+
text = greeting,
|
|
59
|
+
style = TextStyle(
|
|
60
|
+
color = ColorProvider(whiteSubtle),
|
|
61
|
+
fontSize = 11.sp,
|
|
62
|
+
fontWeight = FontWeight.Medium,
|
|
63
|
+
),
|
|
64
|
+
)
|
|
65
|
+
Text(
|
|
66
|
+
text = "Hi, $name!",
|
|
67
|
+
style = TextStyle(
|
|
68
|
+
color = ColorProvider(white),
|
|
69
|
+
fontSize = 22.sp,
|
|
70
|
+
fontWeight = FontWeight.Bold,
|
|
71
|
+
),
|
|
72
|
+
modifier = GlanceModifier.padding(top = 4.dp),
|
|
73
|
+
)
|
|
74
|
+
Spacer(modifier = GlanceModifier.defaultWeight())
|
|
75
|
+
Text(
|
|
76
|
+
text = if (isPro) "⭐ PRO" else "Free plan",
|
|
77
|
+
style = TextStyle(
|
|
78
|
+
color = ColorProvider(if (isPro) gold else whiteVerySubtle),
|
|
79
|
+
fontSize = 11.sp,
|
|
80
|
+
fontWeight = if (isPro) FontWeight.Bold else FontWeight.Medium,
|
|
81
|
+
),
|
|
82
|
+
)
|
|
47
83
|
}
|
|
48
84
|
}
|
|
49
85
|
}
|
|
@@ -4,13 +4,17 @@
|
|
|
4
4
|
"name": "MyWidget",
|
|
5
5
|
"description": "Sample home widget generated by kasy",
|
|
6
6
|
"metadata": {
|
|
7
|
-
"
|
|
7
|
+
"greeting": {
|
|
8
8
|
"type": "string",
|
|
9
|
-
"defaultValue": "
|
|
9
|
+
"defaultValue": "Good morning"
|
|
10
10
|
},
|
|
11
|
-
"
|
|
12
|
-
"type": "
|
|
13
|
-
"defaultValue": "
|
|
11
|
+
"name": {
|
|
12
|
+
"type": "string",
|
|
13
|
+
"defaultValue": "there"
|
|
14
|
+
},
|
|
15
|
+
"isPro": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"defaultValue": "false"
|
|
14
18
|
}
|
|
15
19
|
},
|
|
16
20
|
"isLockScreenWidget": false,
|
|
@@ -3,63 +3,78 @@ import SwiftUI
|
|
|
3
3
|
|
|
4
4
|
struct MyWidgetProvider: TimelineProvider {
|
|
5
5
|
func placeholder(in context: Context) -> MyWidgetEntry {
|
|
6
|
-
MyWidgetEntry(
|
|
7
|
-
date: Date(),
|
|
8
|
-
title: "Hello",
|
|
9
|
-
counter: "0"
|
|
10
|
-
)
|
|
6
|
+
MyWidgetEntry(date: Date(), greeting: "Good morning", name: "there", isPro: false)
|
|
11
7
|
}
|
|
12
8
|
|
|
13
|
-
func getSnapshot(in context: Context, completion: @escaping (MyWidgetEntry) ->
|
|
9
|
+
func getSnapshot(in context: Context, completion: @escaping (MyWidgetEntry) -> Void) {
|
|
14
10
|
let prefs = UserDefaults(suiteName: "group.com.aicrus.firebase.kit")
|
|
15
|
-
|
|
16
|
-
let title = prefs?.string(forKey: "title") ?? "Hello"
|
|
17
|
-
|
|
18
|
-
let counter = prefs?.string(forKey: "counter") ?? "0"
|
|
19
|
-
|
|
20
|
-
let entry = MyWidgetEntry(
|
|
11
|
+
completion(MyWidgetEntry(
|
|
21
12
|
date: Date(),
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
13
|
+
greeting: prefs?.string(forKey: "greeting") ?? "Good morning",
|
|
14
|
+
name: prefs?.string(forKey: "name") ?? "there",
|
|
15
|
+
isPro: prefs?.string(forKey: "isPro") == "true"
|
|
16
|
+
))
|
|
26
17
|
}
|
|
27
18
|
|
|
28
|
-
func getTimeline(in context: Context, completion: @escaping (Timeline<MyWidgetEntry>) ->
|
|
29
|
-
getSnapshot(in: context) {
|
|
30
|
-
|
|
31
|
-
completion(timeline)
|
|
19
|
+
func getTimeline(in context: Context, completion: @escaping (Timeline<MyWidgetEntry>) -> Void) {
|
|
20
|
+
getSnapshot(in: context) { entry in
|
|
21
|
+
completion(Timeline(entries: [entry], policy: .atEnd))
|
|
32
22
|
}
|
|
33
23
|
}
|
|
34
24
|
}
|
|
35
25
|
|
|
36
26
|
struct MyWidgetEntry: TimelineEntry {
|
|
37
27
|
let date: Date
|
|
38
|
-
|
|
39
|
-
let
|
|
40
|
-
|
|
41
|
-
let counter: String
|
|
42
|
-
|
|
28
|
+
let greeting: String
|
|
29
|
+
let name: String
|
|
30
|
+
let isPro: Bool
|
|
43
31
|
}
|
|
44
32
|
|
|
45
33
|
struct MyWidgetWidgetView: View {
|
|
46
34
|
var entry: MyWidgetProvider.Entry
|
|
35
|
+
@Environment(\.widgetFamily) var family
|
|
36
|
+
|
|
37
|
+
private var titleSize: CGFloat {
|
|
38
|
+
switch family {
|
|
39
|
+
case .systemSmall: return 24
|
|
40
|
+
case .systemMedium: return 28
|
|
41
|
+
default: return 34
|
|
42
|
+
}
|
|
43
|
+
}
|
|
47
44
|
|
|
48
45
|
var body: some View {
|
|
49
|
-
VStack(alignment: .leading, spacing:
|
|
50
|
-
Text(entry.
|
|
51
|
-
.font(.system(size:
|
|
52
|
-
.
|
|
53
|
-
.
|
|
54
|
-
.lineLimit(2)
|
|
46
|
+
VStack(alignment: .leading, spacing: 0) {
|
|
47
|
+
Text(entry.greeting)
|
|
48
|
+
.font(.system(size: 11, weight: .medium, design: .rounded))
|
|
49
|
+
.foregroundStyle(.white.opacity(0.55))
|
|
50
|
+
.lineLimit(1)
|
|
55
51
|
|
|
56
|
-
|
|
57
|
-
.font(.system(size: 24, weight: .bold, design: .rounded))
|
|
58
|
-
.foregroundColor(.primary)
|
|
52
|
+
Spacer().frame(height: 6)
|
|
59
53
|
|
|
54
|
+
Text("Hi, \(entry.name)!")
|
|
55
|
+
.font(.system(size: titleSize, weight: .bold, design: .rounded))
|
|
56
|
+
.foregroundStyle(.white)
|
|
57
|
+
.lineLimit(2)
|
|
58
|
+
.minimumScaleFactor(0.75)
|
|
59
|
+
|
|
60
|
+
Spacer()
|
|
61
|
+
|
|
62
|
+
if entry.isPro {
|
|
63
|
+
Label("PRO", systemImage: "star.fill")
|
|
64
|
+
.font(.system(size: 10, weight: .bold, design: .rounded))
|
|
65
|
+
.foregroundStyle(Color(red: 1.0, green: 0.84, blue: 0.0))
|
|
66
|
+
.padding(.horizontal, 8)
|
|
67
|
+
.padding(.vertical, 4)
|
|
68
|
+
.background(Color(red: 1.0, green: 0.84, blue: 0.0).opacity(0.18))
|
|
69
|
+
.clipShape(Capsule())
|
|
70
|
+
} else {
|
|
71
|
+
Text("Free plan")
|
|
72
|
+
.font(.system(size: 10, weight: .medium, design: .rounded))
|
|
73
|
+
.foregroundStyle(.white.opacity(0.4))
|
|
74
|
+
}
|
|
60
75
|
}
|
|
61
|
-
.padding()
|
|
62
76
|
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
|
|
77
|
+
.padding()
|
|
63
78
|
}
|
|
64
79
|
}
|
|
65
80
|
|
|
@@ -69,18 +84,31 @@ struct MyWidgetWidget: Widget {
|
|
|
69
84
|
var body: some WidgetConfiguration {
|
|
70
85
|
StaticConfiguration(kind: kind, provider: MyWidgetProvider()) { entry in
|
|
71
86
|
MyWidgetWidgetView(entry: entry)
|
|
72
|
-
.containerBackground(
|
|
87
|
+
.containerBackground(for: .widget) {
|
|
88
|
+
LinearGradient(
|
|
89
|
+
gradient: Gradient(colors: [
|
|
90
|
+
Color(red: 0.08, green: 0.03, blue: 0.16),
|
|
91
|
+
Color(red: 0.20, green: 0.09, blue: 0.42),
|
|
92
|
+
]),
|
|
93
|
+
startPoint: .topLeading,
|
|
94
|
+
endPoint: .bottomTrailing
|
|
95
|
+
)
|
|
96
|
+
}
|
|
73
97
|
}
|
|
74
98
|
.configurationDisplayName("MyWidget")
|
|
75
99
|
.description("Sample home widget generated by kasy")
|
|
76
|
-
.supportedFamilies([
|
|
77
|
-
.systemSmall,.systemMedium,.systemLarge, // test 2
|
|
78
|
-
])
|
|
100
|
+
.supportedFamilies([.systemSmall, .systemMedium, .systemLarge])
|
|
79
101
|
}
|
|
80
102
|
}
|
|
81
103
|
|
|
82
|
-
#Preview("
|
|
104
|
+
#Preview("Small", as: .systemSmall) {
|
|
105
|
+
MyWidgetWidget()
|
|
106
|
+
} timeline: {
|
|
107
|
+
MyWidgetEntry(date: .now, greeting: "Good morning", name: "Paulo", isPro: true)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
#Preview("Medium", as: .systemMedium) {
|
|
83
111
|
MyWidgetWidget()
|
|
84
112
|
} timeline: {
|
|
85
|
-
MyWidgetEntry(date: .now,
|
|
113
|
+
MyWidgetEntry(date: .now, greeting: "Good afternoon", name: "Paulo", isPro: false)
|
|
86
114
|
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import 'dart:io';
|
|
2
|
+
|
|
1
3
|
import 'package:home_widget/home_widget.dart';
|
|
4
|
+
import 'package:kasy_kit/core/data/models/user.dart';
|
|
2
5
|
import 'package:kasy_kit/core/home_widgets/home_widget_service.dart';
|
|
3
6
|
import 'package:kasy_kit/core/states/user_state_notifier.dart';
|
|
4
7
|
import 'package:logger/logger.dart';
|
|
@@ -18,40 +21,78 @@ class MyWidgetHomeWidget extends _$MyWidgetHomeWidget
|
|
|
18
21
|
@override
|
|
19
22
|
Future<void> update() {
|
|
20
23
|
Logger().i('🔄 Updating MyWidget Home Widget');
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
final
|
|
24
|
+
final user = ref.read(userStateNotifierProvider).user;
|
|
25
|
+
|
|
26
|
+
final name = switch (user) {
|
|
27
|
+
AuthenticatedUserData(:final name)
|
|
28
|
+
when name != null && name.isNotEmpty =>
|
|
29
|
+
name.split(' ').first,
|
|
30
|
+
_ => 'there',
|
|
31
|
+
};
|
|
24
32
|
|
|
25
|
-
|
|
33
|
+
final isPro = switch (user) {
|
|
34
|
+
AuthenticatedUserData(:final subscription) ||
|
|
35
|
+
AnonymousUserData(:final subscription) =>
|
|
36
|
+
subscription?.isActive ?? false,
|
|
37
|
+
_ => false,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
return updateWidget({
|
|
41
|
+
'greeting': _greeting(),
|
|
42
|
+
'name': name,
|
|
43
|
+
'isPro': isPro.toString(),
|
|
44
|
+
});
|
|
26
45
|
}
|
|
27
46
|
|
|
28
|
-
/// Update widget data
|
|
29
|
-
///
|
|
30
|
-
/// This will save data that the widget can read
|
|
31
47
|
Future<void> updateWidget(Map<String, String> data) async {
|
|
32
|
-
await HomeWidget.saveWidgetData<String>(
|
|
33
|
-
|
|
34
|
-
await HomeWidget.saveWidgetData<String>('
|
|
48
|
+
await HomeWidget.saveWidgetData<String>(
|
|
49
|
+
'greeting', data['greeting'] ?? 'Good morning');
|
|
50
|
+
await HomeWidget.saveWidgetData<String>('name', data['name'] ?? 'there');
|
|
51
|
+
await HomeWidget.saveWidgetData<String>(
|
|
52
|
+
'isPro', data['isPro'] ?? 'false');
|
|
35
53
|
|
|
36
|
-
// Trigger widget update
|
|
37
54
|
await HomeWidget.updateWidget(
|
|
38
55
|
name: _androidWidgetName,
|
|
39
56
|
iOSName: _iosWidgetName,
|
|
40
57
|
);
|
|
41
58
|
}
|
|
42
59
|
|
|
43
|
-
/// Get current widget data
|
|
44
60
|
Future<Map<String, dynamic>> getWidgetData() async {
|
|
45
61
|
return {
|
|
46
|
-
'
|
|
47
|
-
'
|
|
48
|
-
defaultValue: '
|
|
62
|
+
'greeting': await HomeWidget.getWidgetData<String>(
|
|
63
|
+
'greeting',
|
|
64
|
+
defaultValue: 'Good morning',
|
|
49
65
|
),
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
'
|
|
53
|
-
|
|
66
|
+
'name': await HomeWidget.getWidgetData<String>(
|
|
67
|
+
'name',
|
|
68
|
+
defaultValue: 'there',
|
|
69
|
+
),
|
|
70
|
+
'isPro': await HomeWidget.getWidgetData<String>(
|
|
71
|
+
'isPro',
|
|
72
|
+
defaultValue: 'false',
|
|
54
73
|
),
|
|
55
74
|
};
|
|
56
75
|
}
|
|
76
|
+
|
|
77
|
+
// Returns a time-of-day greeting in the device language (pt / es / en).
|
|
78
|
+
// Uses Platform.localeName so it works in background isolates without
|
|
79
|
+
// requiring the Flutter locale system to be initialized.
|
|
80
|
+
static String _greeting() {
|
|
81
|
+
final lang = Platform.localeName.split(RegExp(r'[_\-]')).first.toLowerCase();
|
|
82
|
+
final hour = DateTime.now().hour;
|
|
83
|
+
|
|
84
|
+
return switch (lang) {
|
|
85
|
+
'pt' => hour < 12 ? 'Bom dia' : hour < 18 ? 'Boa tarde' : 'Boa noite',
|
|
86
|
+
'es' => hour < 12
|
|
87
|
+
? 'Buenos días'
|
|
88
|
+
: hour < 18
|
|
89
|
+
? 'Buenas tardes'
|
|
90
|
+
: 'Buenas noches',
|
|
91
|
+
_ => hour < 12
|
|
92
|
+
? 'Good morning'
|
|
93
|
+
: hour < 18
|
|
94
|
+
? 'Good afternoon'
|
|
95
|
+
: 'Good evening',
|
|
96
|
+
};
|
|
97
|
+
}
|
|
57
98
|
}
|