Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement VersionControl feature #62

Merged
merged 6 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
35 changes: 18 additions & 17 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ class ExampleApp extends StatelessWidget {
return MaterialApp(
builder: (context, child) {
return NStackWidget(
platformOverride: AppOpenPlatform.android,
child: child!,
);
},
Expand Down Expand Up @@ -49,22 +48,24 @@ class MainScreen extends StatelessWidget {
dialogTitle: localizationAsset.test.dialogTitle,
);

return NStackMessageWidget(
handlerConfiguration: defaultHandlerConfiguration,
child: Scaffold(
appBar: AppBar(
title: Text(localizationAsset.test.testDollarSign),
),
body: Center(
child: MaterialButton(
onPressed: () {
final locale = activeLanguage.locale == 'en-EN'
? const Locale('de-AT')
: const Locale('en-EN');
localization.changeLocalization(locale);
},
child: Text(
'Selected locale: ${activeLanguage.name}',
return NStackVersionControlWidget(
child: NStackMessageWidget(
nivisi marked this conversation as resolved.
Show resolved Hide resolved
handlerConfiguration: defaultHandlerConfiguration,
child: Scaffold(
appBar: AppBar(
title: Text(localizationAsset.test.testDollarSign),
),
body: Center(
child: MaterialButton(
onPressed: () {
final locale = activeLanguage.locale == 'en-EN'
? const Locale('de-AT')
: const Locale('en-EN');
localization.changeLocalization(locale);
},
child: Text(
'Selected locale: ${activeLanguage.name}',
),
),
),
),
Expand Down
196 changes: 196 additions & 0 deletions example/lib/nstack.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@
* - Or use `CustomNstackHandlerConfiguration` if you want to handle the message yourself.
* it has the `onMessage` callback that provides you with the received `Message` object.
*
* 🔖 VERSION CONTROL
*
* Use `NStackVersionControlWidget` to enable version control feature.
* You can configure the localization strings from the NStack console.
*
* 🛠️ IMPORTANT NOTES FOR SDK USERS
*
* The default environment for the NStack SDK is `prod`.
Expand All @@ -47,11 +52,14 @@ import 'package:nstack/models/language.dart';
import 'package:nstack/models/localize_index.dart';
import 'package:nstack/models/message.dart';
import 'package:nstack/models/nstack_config.dart';
import 'package:nstack/models/update.dart';
import 'package:nstack/models/update_view_request.dart';
import 'package:nstack/sdk/nstack_sdk.dart';
import 'package:nstack/sdk/localization/nstack_localization.dart';
import 'package:nstack/partial/section_key_delegate.dart';
import 'package:flutter/cupertino.dart' as cupertino;
import 'package:flutter/material.dart' as material;
import 'package:nstack/utils/log_util.dart';
import 'package:url_launcher/url_launcher.dart';

export 'package:nstack/models/app_open_platform.dart';
Expand Down Expand Up @@ -463,6 +471,194 @@ class NStackMessageDialog extends StatelessWidget {
}
}

/*
*
* NStack Version Control
*
*/

class NStackVersionControlWidget extends StatefulWidget {
const NStackVersionControlWidget({
super.key,
this.child,
});

final Widget? child;

@override
State<StatefulWidget> createState() => _NStackVersionControlWidgetSate();
}

class _NStackVersionControlWidgetSate
extends State<NStackVersionControlWidget> {
late final StreamSubscription _versionInfoSubscription;
@override
void initState() {
super.initState();

WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
_versionInfoSubscription = context
.nstack.appVersionControl.onVersionUpdateNotification
.listen(_onVersionUpdateNotification);
});
}

@override
void dispose() {
_versionInfoSubscription.cancel();
super.dispose();
}

void _onVersionUpdateNotification(Update update_info) {
NStackAppUpdateInfoDialog.show(context, update_info: update_info);
}

@override
Widget build(BuildContext context) {
return widget.child ?? const SizedBox();
}
}

class NStackAppUpdateInfoDialog extends StatelessWidget {
const NStackAppUpdateInfoDialog._({
Key? key,
required this.update_info,
}) : super(key: key);

/// App update info that was received.
final Update update_info;

/// Displays the dialog.
static Future<void> show(
BuildContext context, {
required Update update_info,
}) {
Widget builder(BuildContext context) {
return NStackAppUpdateInfoDialog._(
update_info: update_info,
);
}

final showDialog = Platform.isIOS
? cupertino.showCupertinoDialog(context: context, builder: builder)
: material.showDialog(context: context, builder: builder);
return showDialog;
hassan-saleh-ml marked this conversation as resolved.
Show resolved Hide resolved
}

@override
Widget build(BuildContext context) {
final titleWidget = update_info.newerVersion != null
? Text(update_info.newerVersion!.localizations.title)
: update_info.newInThisVersion?.localizations != null
? Text(update_info.newInThisVersion!.localizations.title)
: null;

final messageWidget = update_info.newerVersion != null
? Text(update_info.newerVersion!.localizations.message)
: update_info.newInThisVersion?.localizations != null
? Text(update_info.newInThisVersion!.localizations.message)
: null;

final dismissWidget =
update_info.newerVersion?.localizations.negativeBtn != null
? Text(update_info.newerVersion!.localizations.negativeBtn!)
: update_info.newInThisVersion?.localizations.negativeBtn != null
? Text(update_info.newInThisVersion!.localizations.negativeBtn!)
: const Text('OK');

final updateWidget =
update_info.newerVersion?.localizations.positiveBtn != null
? Text(update_info.newerVersion!.localizations.positiveBtn!)
: const Text('Update');

final isUriValid = update_info.newerVersion?.link != null;

final urlLaunchAction = !isUriValid
? null
: () async {
if (update_info.newerVersion?.lastId != null) {
await context.nstack.appVersionControl.setUpdateInfoViewed(
updateId: update_info.newerVersion!.lastId,
answer: UpdateViewAnswer.yes,
type: UpdateViewType.newer_version,
);
}
try {
await launchUrl(update_info.newerVersion!.link!);
} catch (e) {
LogUtil.log(
'NStackVersionControl --> Filed to open URL with error: ${e.toString()}',
);
}

if (context.mounted &&
update_info.newerVersion?.state != UpdateState.force) {
Navigator.of(context).pop();
}
};

final dismissAction = () async {
if (update_info.newInThisVersion != null) {
await context.nstack.appVersionControl.setUpdateInfoViewed(
updateId: update_info.newInThisVersion!.lastId,
answer: UpdateViewAnswer.yes,
type: UpdateViewType.new_in_version,
);
} else if (update_info.newerVersion?.lastId != null) {
await context.nstack.appVersionControl.setUpdateInfoViewed(
updateId: update_info.newerVersion!.lastId,
answer: UpdateViewAnswer.yes,
type: UpdateViewType.newer_version,
);
}
if (context.mounted) {
Navigator.of(context).pop();
}
};

if (Platform.isIOS) {
return cupertino.CupertinoAlertDialog(
title: titleWidget,
content: messageWidget,
actions: [
if (update_info.newerVersion?.state != UpdateState.force ||
update_info.newInThisVersion != null)
cupertino.CupertinoDialogAction(
onPressed: dismissAction,
child: dismissWidget,
),
if (update_info.newerVersion?.state == UpdateState.remind ||
update_info.newerVersion?.state == UpdateState.force)
cupertino.CupertinoDialogAction(
isDefaultAction: true,
onPressed: urlLaunchAction,
child: updateWidget,
),
],
);
}

return material.AlertDialog(
title: titleWidget,
content: messageWidget,
actions: [
if (update_info.newerVersion?.state == UpdateState.remind ||
update_info.newerVersion?.state == UpdateState.force)
material.TextButton(
onPressed: urlLaunchAction,
child: updateWidget,
),
if (update_info.newerVersion?.state != UpdateState.force ||
update_info.newInThisVersion != null)
material.TextButton(
onPressed: dismissAction,
child: dismissWidget,
),
],
);
}
}

/*
*
* NStack Flutter Extensions
Expand Down
19 changes: 10 additions & 9 deletions lib/models/app_open_data.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import 'package:nstack/models/app_update.dart';
import 'package:nstack/models/localize_index.dart';
import 'package:nstack/models/message.dart';
import 'package:nstack/models/rate_reminder.dart';
import 'package:nstack/models/terms.dart';
import 'package:nstack/models/update.dart';
import 'package:nstack/other/extensions.dart';

class AppOpenData {
final int? count;
final AppUpdate? update;
final Update? update;
final List<LocalizeIndex>? localize;
final String? platform;
final DateTime? createdAt;
Expand All @@ -31,22 +31,23 @@ class AppOpenData {
factory AppOpenData.fromJson(Map json) {
return AppOpenData(
count: json['count'],
update: (json['update'] as Map?)?.let((it) => AppUpdate.fromJson(it)),
update: (json['update'] as Map<String, dynamic>?)
?.let((item) => Update.fromJson(item)),
localize: (json['localize'] as List?)?.let(
(it) => it.map((e) => LocalizeIndex.fromJson(e)).toList(),
(item) => item.map((e) => LocalizeIndex.fromJson(e)).toList(),
),
platform: json['platform'],
createdAt: (json['created_at'] as String?)?.let(
(it) => DateTime.parse(it),
(item) => DateTime.parse(item),
),
updatedAt: (json['last_updated'] as String?)?.let(
(it) => DateTime.parse(it),
(item) => DateTime.parse(item),
),
message: (json['message'] as Map?)?.let((it) => Message.fromJson(it)),
message: (json['message'] as Map?)?.let((item) => Message.fromJson(item)),
rateReminder: json['rateReminder']?.let(
(it) => RateReminder.fromJson(it),
(item) => RateReminder.fromJson(item),
),
terms: json['terms']?.let((it) => it),
terms: json['terms']?.let((item) => item),
);
}
}
41 changes: 0 additions & 41 deletions lib/models/app_update.dart

This file was deleted.

6 changes: 0 additions & 6 deletions lib/models/app_update_state.dart

This file was deleted.

Loading
Loading