macOS widgets
This commit is contained in:
parent
efbf3cb73d
commit
5f819bd0b4
|
|
@ -9,6 +9,7 @@ import 'package:flutter/services.dart';
|
|||
// Package imports:
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:flutter_styled_toast/flutter_styled_toast.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/dashboard_model.dart';
|
||||
import 'package:invoiceninja_flutter/redux/auth/auth_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/reports/reports_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/settings/settings_actions.dart';
|
||||
|
|
@ -1405,20 +1406,27 @@ void _showAbout(BuildContext context) async {
|
|||
),
|
||||
]);
|
||||
} else {
|
||||
final json = jsonEncode(WidgetData(
|
||||
url: formatApiUrl(state.authState.url),
|
||||
companyId: state.account.defaultCompanyId,
|
||||
dateRanges: Map.fromIterable(DateRange.values,
|
||||
key: (dynamic item) => toSnakeCase('$item'),
|
||||
value: (dynamic item) =>
|
||||
localization.lookup('$item')),
|
||||
companies: {
|
||||
for (var userCompany in state.userCompanyStates
|
||||
.where((state) => state.company.hasName))
|
||||
userCompany.company.id:
|
||||
WidgetCompany.fromUserCompany(
|
||||
userCompanyState: userCompany,
|
||||
staticState: state.staticState,
|
||||
)
|
||||
}));
|
||||
|
||||
print('## Set Widget Data: $json');
|
||||
|
||||
await UserDefaults.setString(
|
||||
'widget_data',
|
||||
jsonEncode(WidgetData(
|
||||
url: formatApiUrl(state.authState.url),
|
||||
companyId: state.account.defaultCompanyId,
|
||||
companies: {
|
||||
for (var userCompany
|
||||
in state.userCompanyStates.where((state) => state.company.hasName))
|
||||
userCompany.company.id:
|
||||
WidgetCompany.fromUserCompany(
|
||||
userCompanyState: userCompany,
|
||||
staticState: state.staticState,)
|
||||
})),
|
||||
'group.com.invoiceninja.app');
|
||||
'widget_data', json, 'group.com.invoiceninja.app');
|
||||
await WidgetKit.reloadAllTimelines();
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -101,22 +101,26 @@ class WidgetData {
|
|||
this.url,
|
||||
this.companies,
|
||||
this.companyId,
|
||||
this.dateRanges,
|
||||
});
|
||||
|
||||
WidgetData.fromJson(Map<String, dynamic> json)
|
||||
: url = json['url'],
|
||||
companyId = json['company_id'],
|
||||
companies = json['companies'];
|
||||
companies = json['companies'],
|
||||
dateRanges = json['date_ranges'];
|
||||
|
||||
Map<String, dynamic> toJson() => <String, dynamic>{
|
||||
'companies': companies,
|
||||
'company_id': companyId,
|
||||
'url': url,
|
||||
'date_ranges': dateRanges,
|
||||
};
|
||||
|
||||
final String url;
|
||||
final String companyId;
|
||||
final Map<String, WidgetCompany> companies;
|
||||
final Map<String, String> dateRanges;
|
||||
}
|
||||
|
||||
class WidgetCompany {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import Intents
|
||||
|
||||
class IntentHandler: INExtension, ConfigurationIntentHandling {
|
||||
|
||||
private func loadWidgetData() -> WidgetData {
|
||||
let sharedDefaults = UserDefaults(suiteName: "group.com.invoiceninja.app")
|
||||
var widgetData: WidgetData = WidgetData(url: "", companyId: "", companies: [:])
|
||||
var widgetData: WidgetData = WidgetData(url: "", companyId: "", companies: [:], dateRanges: [:])
|
||||
|
||||
if let sharedDefaults = sharedDefaults {
|
||||
do {
|
||||
|
|
@ -53,6 +52,25 @@ class IntentHandler: INExtension, ConfigurationIntentHandling {
|
|||
let currency = company?.currencies[company!.currencyId];
|
||||
return Currency(identifier: currency!.id, display: currency!.name)
|
||||
}
|
||||
|
||||
func provideDateRangeOptionsCollection(for intent: ConfigurationIntent) async throws -> INObjectCollection<DateRange> {
|
||||
let widgetData = loadWidgetData()
|
||||
|
||||
|
||||
let dateRanges = widgetData.dateRanges.keys.map { dateRange in
|
||||
DateRange(identifier: dateRange, display: widgetData.dateRanges[dateRange]!)
|
||||
}
|
||||
|
||||
return INObjectCollection(items: dateRanges)
|
||||
}
|
||||
|
||||
func defaultDateRange(for intent: ConfigurationIntent) -> DateRange? {
|
||||
let widgetData = loadWidgetData()
|
||||
let defaultDateRange = "last30_days";
|
||||
let dateRamge = widgetData.dateRanges[defaultDateRange]!;
|
||||
return DateRange(identifier: defaultDateRange, display: dateRamge)
|
||||
}
|
||||
|
||||
|
||||
override func handler(for intent: INIntent) -> Any {
|
||||
return self
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@
|
|||
<key>INIntentIneligibleForSuggestions</key>
|
||||
<true/>
|
||||
<key>INIntentLastParameterTag</key>
|
||||
<integer>9</integer>
|
||||
<integer>11</integer>
|
||||
<key>INIntentName</key>
|
||||
<string>Configuration</string>
|
||||
<key>INIntentParameters</key>
|
||||
|
|
@ -219,6 +219,63 @@
|
|||
<key>INIntentParameterType</key>
|
||||
<string>Integer</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>INIntentParameterConfigurable</key>
|
||||
<true/>
|
||||
<key>INIntentParameterDisplayName</key>
|
||||
<string>Date Range</string>
|
||||
<key>INIntentParameterDisplayNameID</key>
|
||||
<string>hGdezL</string>
|
||||
<key>INIntentParameterDisplayPriority</key>
|
||||
<integer>4</integer>
|
||||
<key>INIntentParameterName</key>
|
||||
<string>dateRange</string>
|
||||
<key>INIntentParameterObjectType</key>
|
||||
<string>DateRange</string>
|
||||
<key>INIntentParameterObjectTypeNamespace</key>
|
||||
<string>88xZPY</string>
|
||||
<key>INIntentParameterPromptDialogs</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>INIntentParameterPromptDialogCustom</key>
|
||||
<true/>
|
||||
<key>INIntentParameterPromptDialogType</key>
|
||||
<string>Configuration</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>INIntentParameterPromptDialogCustom</key>
|
||||
<true/>
|
||||
<key>INIntentParameterPromptDialogType</key>
|
||||
<string>Primary</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>INIntentParameterPromptDialogCustom</key>
|
||||
<true/>
|
||||
<key>INIntentParameterPromptDialogFormatString</key>
|
||||
<string>There are ${count} options matching ‘${dateRange}’.</string>
|
||||
<key>INIntentParameterPromptDialogFormatStringID</key>
|
||||
<string>M1c9EE</string>
|
||||
<key>INIntentParameterPromptDialogType</key>
|
||||
<string>DisambiguationIntroduction</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>INIntentParameterPromptDialogCustom</key>
|
||||
<true/>
|
||||
<key>INIntentParameterPromptDialogFormatString</key>
|
||||
<string>Just to confirm, you wanted ‘${dateRange}’?</string>
|
||||
<key>INIntentParameterPromptDialogFormatStringID</key>
|
||||
<string>YL2DLe</string>
|
||||
<key>INIntentParameterPromptDialogType</key>
|
||||
<string>Confirmation</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>INIntentParameterSupportsDynamicEnumeration</key>
|
||||
<true/>
|
||||
<key>INIntentParameterTag</key>
|
||||
<integer>11</integer>
|
||||
<key>INIntentParameterType</key>
|
||||
<string>Object</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>INIntentResponse</key>
|
||||
<dict>
|
||||
|
|
@ -376,6 +433,69 @@
|
|||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>INTypeDisplayName</key>
|
||||
<string>Date Range</string>
|
||||
<key>INTypeDisplayNameID</key>
|
||||
<string>cJBTgC</string>
|
||||
<key>INTypeLastPropertyTag</key>
|
||||
<integer>99</integer>
|
||||
<key>INTypeName</key>
|
||||
<string>DateRange</string>
|
||||
<key>INTypeProperties</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>INTypePropertyDefault</key>
|
||||
<true/>
|
||||
<key>INTypePropertyDisplayPriority</key>
|
||||
<integer>1</integer>
|
||||
<key>INTypePropertyName</key>
|
||||
<string>identifier</string>
|
||||
<key>INTypePropertyTag</key>
|
||||
<integer>1</integer>
|
||||
<key>INTypePropertyType</key>
|
||||
<string>String</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>INTypePropertyDefault</key>
|
||||
<true/>
|
||||
<key>INTypePropertyDisplayPriority</key>
|
||||
<integer>2</integer>
|
||||
<key>INTypePropertyName</key>
|
||||
<string>displayString</string>
|
||||
<key>INTypePropertyTag</key>
|
||||
<integer>2</integer>
|
||||
<key>INTypePropertyType</key>
|
||||
<string>String</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>INTypePropertyDefault</key>
|
||||
<true/>
|
||||
<key>INTypePropertyDisplayPriority</key>
|
||||
<integer>3</integer>
|
||||
<key>INTypePropertyName</key>
|
||||
<string>pronunciationHint</string>
|
||||
<key>INTypePropertyTag</key>
|
||||
<integer>3</integer>
|
||||
<key>INTypePropertyType</key>
|
||||
<string>String</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>INTypePropertyDefault</key>
|
||||
<true/>
|
||||
<key>INTypePropertyDisplayPriority</key>
|
||||
<integer>4</integer>
|
||||
<key>INTypePropertyName</key>
|
||||
<string>alternativeSpeakableMatches</string>
|
||||
<key>INTypePropertySupportsMultipleValues</key>
|
||||
<true/>
|
||||
<key>INTypePropertyTag</key>
|
||||
<integer>4</integer>
|
||||
<key>INTypePropertyType</key>
|
||||
<string>SpeakableString</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ struct Provider: IntentTimelineProvider {
|
|||
|
||||
SimpleEntry(date: Date(),
|
||||
configuration: ConfigurationIntent(),
|
||||
widgetData: WidgetData(url: "url", companyId: "", companies: [:]),
|
||||
widgetData: WidgetData(url: "url", companyId: "", companies: [:], dateRanges: [:]),
|
||||
field: "Active Invoices",
|
||||
value: "$100.00")
|
||||
}
|
||||
|
|
@ -25,7 +25,7 @@ struct Provider: IntentTimelineProvider {
|
|||
|
||||
let entry = SimpleEntry(date: Date(),
|
||||
configuration: configuration,
|
||||
widgetData: WidgetData(url: "url", companyId: "", companies: [:]),
|
||||
widgetData: WidgetData(url: "url", companyId: "", companies: [:], dateRanges: [:]),
|
||||
field: "Active Invoices",
|
||||
value: "$100.00")
|
||||
|
||||
|
|
@ -146,11 +146,13 @@ struct WidgetData: Decodable, Hashable {
|
|||
let url: String
|
||||
let companyId: String
|
||||
let companies: [String: WidgetCompany]
|
||||
let dateRanges: [String: String]
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case url
|
||||
case companyId = "company_id"
|
||||
case companies
|
||||
case dateRanges = "date_ranges"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -158,6 +160,7 @@ struct WidgetCompany: Decodable, Hashable {
|
|||
let id: String
|
||||
let name: String
|
||||
let token: String
|
||||
let firstMonthOfYear: Int
|
||||
let accentColor: String
|
||||
let currencyId: String
|
||||
let currencies: [String: WidgetCurrency]
|
||||
|
|
@ -166,6 +169,7 @@ struct WidgetCompany: Decodable, Hashable {
|
|||
case id
|
||||
case name
|
||||
case token
|
||||
case firstMonthOfYear = "first_month_of_year"
|
||||
case accentColor = "accent_color"
|
||||
case currencyId = "currency_id"
|
||||
case currencies
|
||||
|
|
@ -257,7 +261,7 @@ struct DashboardWidget_Previews: PreviewProvider {
|
|||
static var previews: some View {
|
||||
let entry = SimpleEntry(date: Date(),
|
||||
configuration: ConfigurationIntent(),
|
||||
widgetData: WidgetData(url: "url", companyId: "", companies: [:]),
|
||||
widgetData: WidgetData(url: "url", companyId: "", companies: [:], dateRanges: [:]),
|
||||
field: "Active Invoices",
|
||||
value: "$100.00")
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue