Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ jobs:
name: Smarthome ${{ github.ref }}
draft: true
prerelease: false
generateReleaseNotes: true


create-build:
Expand Down Expand Up @@ -176,3 +175,4 @@ jobs:
prerelease: false
allowUpdates: true
artifacts: smarthome_${{ matrix.target }}${{ matrix.asset_extension }}
generateReleaseNotes: true
8 changes: 6 additions & 2 deletions lib/devices/device_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import 'package:smarthome/helper/iterable_extensions.dart';
import 'package:smarthome/helper/preference_manager.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_riverpod/legacy.dart';
import 'package:smarthome/main.dart';

import '../icons/smarthome_icons.dart';
import 'device_exporter.dart';
Expand Down Expand Up @@ -400,6 +401,9 @@ class DeviceManager extends _$DeviceManager {
connection.state != HubConnectionState.Connected) {
return current;
}
final firebaseInitialized = await ref.read(
firebaseInitializedProvider.future,
);

if (diffIds.any((final element) => element.action == Action.added)) {
final deviceIds = diffIds
Expand All @@ -411,7 +415,7 @@ class DeviceManager extends _$DeviceManager {
for (final id in deviceIds) {
if (PreferencesManager.instance.containsKey("SHD$id")) continue;
PreferencesManager.instance.setInt("SHD$id", id);
if (Platform.isAndroid || Platform.isIOS) {
if (firebaseInitialized && (Platform.isAndroid || Platform.isIOS)) {
FirebaseMessaging.instance.subscribeToTopic("device_$id");
}
}
Expand All @@ -425,7 +429,7 @@ class DeviceManager extends _$DeviceManager {

for (final diffId in diffIds) {
current.removeWhere((final d) => d.id == diffId.id);
if (Platform.isAndroid || Platform.isIOS) {
if (firebaseInitialized && (Platform.isAndroid || Platform.isIOS)) {
FirebaseMessaging.instance.unsubscribeFromTopic("device_$diffId");
}
}
Expand Down
23 changes: 17 additions & 6 deletions lib/devices/generic/widgets/edits/basic_edit_types.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,24 @@ import 'package:smarthome/helper/connection_manager.dart';
import 'package:smarthome/restapi/swagger.swagger.dart';

class BasicIcon extends ConsumerWidget {
const BasicIcon({super.key, required this.info});
const BasicIcon({
super.key,
required this.id,
this.valueModel,
required this.info,
});
final LayoutBasePropertyInfo info;
final int id;
final ValueStore? valueModel;

@override
Widget build(final BuildContext context, final WidgetRef ref) {
if (info.editInfo == null) return const SizedBox();
final edit = GenericDevice.getEditParameter(null, info.editInfo!, "icon");
final edit = GenericDevice.getEditParameter(
valueModel,
info.editInfo!,
"icon",
);
if (edit == null) return const SizedBox();
final raw = edit.extensionData ?? {};
final color = raw["Color"] as int?;
Expand Down Expand Up @@ -59,7 +70,7 @@ class BasicButton extends ConsumerWidget {
final tempSettingsDialog = editInfo.dialog == "HeaterConfig";
final child = Row(
children: [
BasicIcon(info: info),
BasicIcon(id: id, valueModel: valueModel, info: info),
Text(
editInfo.display!,
style: TextStyle(
Expand Down Expand Up @@ -128,7 +139,7 @@ class BasicDropdown extends ConsumerWidget {
final editInfo = info.editInfo!;
return Row(
children: [
BasicIcon(info: info),
BasicIcon(id: id, valueModel: valueModel, info: info),
DropdownButton(
items: editInfo.editParameter
.map(
Expand Down Expand Up @@ -221,7 +232,7 @@ class BasicToggle extends ConsumerWidget {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
BasicIcon(info: info),
BasicIcon(id: id, valueModel: valueModel, info: info),
if (edit.displayName != null) Text(edit.displayName!),
Switch(
onChanged: ((final _) async {
Expand Down Expand Up @@ -310,7 +321,7 @@ class BasicSlider extends HookConsumerWidget {

return Row(
children: [
BasicIcon(info: info),
BasicIcon(id: id, valueModel: valueModel, info: info),
SliderTheme(
data: sliderTheme,
child: Slider(
Expand Down
2 changes: 1 addition & 1 deletion lib/devices/generic_device.dart
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ class GenericDevice extends Device<BaseModel> {
case "iconbutton":
return BasicIconButton(id: id, valueModel: valueModel, info: e);
case "icon":
return BasicIcon(info: e);
return BasicIcon(id: id, valueModel: valueModel, info: e);
case "radial":
return GaugeEdit(id: id, valueModel: valueModel, info: e);
// case EditType.input:
Expand Down
2 changes: 1 addition & 1 deletion lib/devices/heater/heater_temp_settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class HeaterTempSettings extends HookWidget {
final configs = <HeaterConfig>[];
final tod = selectedDate;
for (int i = 0; i < 7; i++) {
final flag = 1 << (i + 1);
final flag = 1 << i;

if (selected & flag == 0) continue;
final dayOfWeek = flagToDayOfWeekMap[flag]!;
Expand Down
162 changes: 94 additions & 68 deletions lib/helper/notification_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:smarthome/helper/connection_manager.dart';
import 'package:smarthome/helper/iterable_extensions.dart';
import 'package:smarthome/helper/number_extensions.dart';
import 'package:smarthome/helper/preference_manager.dart';
import 'package:smarthome/main.dart';
import 'package:smarthome/models/notification_topic.dart';
import 'package:smarthome/notifications/app_notification.dart';

Expand All @@ -32,7 +33,7 @@ class NotificationService extends _$NotificationService {
static int notificationId = 0;

static final Map<Type, Map<String, void Function(dynamic notification)>>
_callbacks = {};
_callbacks = {};

@override
Future build() async {
Expand All @@ -54,8 +55,9 @@ class NotificationService extends _$NotificationService {
void processNotification(final List<Object?>? arguments) {
final notification = AppNotification.fromJson(arguments!.first as dynamic);
final topics = PreferencesManager.instance.getNotificationTopics();
final topic =
topics.firstOrDefault((final x) => x.topic == notification.topic);
final topic = topics.firstOrDefault(
(final x) => x.topic == notification.topic,
);
if (topic == null) return;
if (notification.wasOneTime) {
final idx = topics.indexOf(topic);
Expand All @@ -65,7 +67,11 @@ class NotificationService extends _$NotificationService {

if (notification is VisibleAppNotification) {
flutterLocalNotificationsPlugin.show(
notificationId++, notification.title, notification.body, null);
notificationId++,
notification.title,
notification.body,
null,
);
}

final callbacks = _callbacks[notification.runtimeType];
Expand All @@ -77,17 +83,22 @@ class NotificationService extends _$NotificationService {
}

static String registerCallback<T>(
final String id, final Function(T parameter) func) {
final String id,
final Function(T parameter) func,
) {
return _registerCallback(id, T, (final p) => func(p));
}

static String _registerCallback(final String id, final Type type,
final Function(dynamic parameter) func) {
static String _registerCallback(
final String id,
final Type type,
final Function(dynamic parameter) func,
) {
if (_callbacks.containsKey(type)) {
_callbacks[type]!.addAll({id: func});
} else {
_callbacks.addAll({
type: {id: func}
type: {id: func},
});
}

Expand Down Expand Up @@ -121,63 +132,72 @@ class NotificationService extends _$NotificationService {
for (final grp in grouped.entries) {
final widgets = <Widget>[];
for (final (_, id, element) in grp.value) {
final topic = useState(topics.firstWhere(
(final x) =>
x.uniqueName == element.uniqueName && x.deviceId == id,
orElse: () {
final oneTime = element.times == 1;
final String topic;
if (oneTime) {
topic = "";
} else if (id == null) {
topic = element.uniqueName;
} else {
topic = "${element.uniqueName}_${id.toHex()}";
}
return NotificationTopic(
final topic = useState(
topics.firstWhere(
(final x) =>
x.uniqueName == element.uniqueName && x.deviceId == id,
orElse: () {
final oneTime = element.times == 1;
final String topic;
if (oneTime) {
topic = "";
} else if (id == null) {
topic = element.uniqueName;
} else {
topic = "${element.uniqueName}_${id.toHex()}";
}
return NotificationTopic(
enabled: false,
deviceId: id,
oneTime: oneTime,
topic: topic,
uniqueName: element.uniqueName);
},
));
uniqueName: element.uniqueName,
);
},
),
);
if (!topics.contains(topic.value)) topics.add(topic.value);

final checked = useState(topic.value.enabled);
widgets.add(CheckboxListTile(
value: checked.value,
title: Text(element.translatableName),
onChanged: (final value) async {
checked.value = value ?? false;
if (topic.value.topic == "") {
final res = await api.notificationNextNotificationIdGet(
uniqueName: topic.value.uniqueName,
deviceId: id,
);
final notificationTopic = res.bodyOrThrow;
print(notificationTopic);
final idx = topics.indexOf(topic.value);
topic.value = topic.value.copyWith(
topic: notificationTopic, enabled: checked.value);
topics[idx] = topic.value;
} else if (checked.value) {
final idx = topics.indexOf(topic.value);
topic.value = topic.value.copyWith(enabled: checked.value);
topics[idx] = topic.value;
} else {
final idx = topics.indexOf(topic.value);
topic.value = topic.value.copyWith(enabled: checked.value);
topics[idx] = topic.value;
}
},
));
widgets.add(
CheckboxListTile(
value: checked.value,
title: Text(element.translatableName),
onChanged: (final value) async {
checked.value = value ?? false;
if (topic.value.topic == "") {
final res = await api.notificationNextNotificationIdGet(
uniqueName: topic.value.uniqueName,
deviceId: id,
);
final notificationTopic = res.bodyOrThrow;
print(notificationTopic);
final idx = topics.indexOf(topic.value);
topic.value = topic.value.copyWith(
topic: notificationTopic,
enabled: checked.value,
);
topics[idx] = topic.value;
} else if (checked.value) {
final idx = topics.indexOf(topic.value);
topic.value = topic.value.copyWith(enabled: checked.value);
topics[idx] = topic.value;
} else {
final idx = topics.indexOf(topic.value);
topic.value = topic.value.copyWith(enabled: checked.value);
topics[idx] = topic.value;
}
},
),
);
}
expansionTiles.add(ExpansionTile(
title: Text(grp.key),
initiallyExpanded: grouped.length == 1,
children: widgets,
));
expansionTiles.add(
ExpansionTile(
title: Text(grp.key),
initiallyExpanded: grouped.length == 1,
children: widgets,
),
);
}

return SingleChildScrollView(
Expand All @@ -194,26 +214,32 @@ class NotificationService extends _$NotificationService {
content: hookedBuilder,
actions: <Widget>[
TextButton(
child: Text("Abbrechen"),
onPressed: () {
Navigator.pop(context, false);
}),
child: Text("Abbrechen"),
onPressed: () {
Navigator.pop(context, false);
},
),
TextButton(
child: Text("Speichern"),
onPressed: () {
Navigator.pop(context, true);
})
child: Text("Speichern"),
onPressed: () {
Navigator.pop(context, true);
},
),
],
);
final dialogRes =
await showDialog(context: context, builder: (final ctx) => ad);
final dialogRes = await showDialog(
context: context,
builder: (final ctx) => ad,
);
if (dialogRes == true) {
final validTopics = topics
.where((final x) => x.topic.isNotEmpty && (!x.oneTime || x.enabled))
.toList();

PreferencesManager.instance.setNotificationTopics(validTopics);
if (Platform.isAndroid || Platform.isIOS) {

final init = await ref.watch(firebaseInitializedProvider.future);
if (init && (Platform.isAndroid || Platform.isIOS)) {
for (final topic in validTopics) {
if (topic.enabled) {
FirebaseMessaging.instance.subscribeToTopic(topic.topic);
Expand Down
Loading