diff --git a/.github/workflows/tag.yaml b/.github/oldworkflows/tag.yaml similarity index 67% rename from .github/workflows/tag.yaml rename to .github/oldworkflows/tag.yaml index f516cc7..66de26c 100644 --- a/.github/workflows/tag.yaml +++ b/.github/oldworkflows/tag.yaml @@ -1,24 +1,24 @@ -name: "tag" -on: - push: - branches: - - "development" - pull_request: - branches: - - "development" +# name: "tag" +# on: +# push: +# branches: +# - "development" +# pull_request: +# branches: +# - "development" -jobs: - tag: - name: "git tag" - runs-on: "ubuntu-latest" - steps: - - uses: actions/checkout@v3 +# jobs: +# tag: +# name: "git tag" +# runs-on: "ubuntu-latest" +# steps: +# - uses: actions/checkout@v3 - - name: Bump version and push tag - id: tag_version - uses: mathieudutour/github-tag-action@v6.1 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} +# - name: Bump version and push tag +# id: tag_version +# uses: mathieudutour/github-tag-action@v6.1 +# with: +# github_token: ${{ secrets.GITHUB_TOKEN }} # - name: Create a GitHub release # uses: ncipollo/release-action@v1 # with: diff --git a/lib/components/HeadingListTile.component.dart b/lib/components/HeadingListTile.component.dart new file mode 100644 index 0000000..f066ae8 --- /dev/null +++ b/lib/components/HeadingListTile.component.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; + +class HeadingListTile extends StatelessWidget { + const HeadingListTile({required this.labelText, super.key}); + + final String labelText; + + @override + Widget build(BuildContext context) { + return ListTile( + title: Text( + labelText, + style: Theme.of(context).textTheme.headline5, + )); + } +} diff --git a/lib/components/ListViewCard.component.dart b/lib/components/ListViewCard.component.dart new file mode 100644 index 0000000..87ccefe --- /dev/null +++ b/lib/components/ListViewCard.component.dart @@ -0,0 +1,53 @@ +import 'package:badges/badges.dart'; +import 'package:flutter/material.dart'; +import 'package:hacklytics_checkin_flutter/components/HeadingListTile.component.dart'; + +class ListViewCard extends StatelessWidget { + const ListViewCard({this.labelText = "", required this.children, super.key}); + + final String labelText; + final List children; + + @override + Widget build(BuildContext context) { + return labelText.isEmpty ? _buildNoLabel() : _buildWithLabel(); + } + + _buildNoLabel() { + return Card( + child: ListView( + shrinkWrap: true, + physics: const ClampingScrollPhysics(), + children: children, + ), + ); + } + + _buildWithLabel() { + return Card( + child: ListView( + shrinkWrap: true, + physics: const ClampingScrollPhysics(), + children: [ + HeadingListTile(labelText: labelText), + // const Divider(), + ...children + ], + ), + ); + } +} + +// Badge( +// badgeContent: Text(labelText), +// shape: BadgeShape.square, +// alignment: Alignment.topRight, +// position: BadgePosition.topEnd(top: 2, end: 2), +// borderRadius: BorderRadius.circular(10), +// child: Card( +// child: ListView( +// shrinkWrap: true, +// physics: const ClampingScrollPhysics(), +// children: children, +// ), +// )); diff --git a/lib/components/toast.component.dart b/lib/components/toast.component.dart new file mode 100644 index 0000000..b9002c8 --- /dev/null +++ b/lib/components/toast.component.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; + +class ConfirmToast extends StatelessWidget { + const ConfirmToast({required this.labelText, super.key}); + + final String labelText; + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(25.0), + color: Colors.green.shade500, + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.check), + const SizedBox( + width: 12.0, + ), + Text(labelText), + ], + ), + ); + } +} + +class ErrorToast extends StatelessWidget { + const ErrorToast({required this.labelText, super.key}); + + final String labelText; + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(25.0), + color: Colors.red.shade500, + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.error), + const SizedBox( + width: 12.0, + ), + Text(labelText), + ], + ), + ); + } +} diff --git a/lib/main.dart b/lib/main.dart index 6570d52..69bfaa3 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,6 +2,8 @@ import 'package:flutter/material.dart'; import 'App.dart'; +GlobalKey globalKey = GlobalKey(); + void main() { runApp(const MyApp()); } diff --git a/lib/view/Home.view.dart b/lib/view/Home.view.dart index 3f3274d..999b97d 100644 --- a/lib/view/Home.view.dart +++ b/lib/view/Home.view.dart @@ -3,6 +3,7 @@ import 'package:amplify_auth_cognito/amplify_auth_cognito.dart'; import 'package:amplify_flutter/amplify_flutter.dart'; import 'package:flutter/material.dart'; +import 'package:hacklytics_checkin_flutter/components/ListViewCard.component.dart'; import 'package:hacklytics_checkin_flutter/components/statuscard.component.dart'; import 'package:hacklytics_checkin_flutter/models/ModelProvider.dart'; @@ -81,7 +82,7 @@ class _HomeViewState extends State { leading: const Icon(Icons.settings), onTap: () { Navigator.push(context, MaterialPageRoute(builder: (context) { - return const SettingsView(); + return SettingsView(user: _user); })); }, ), @@ -138,43 +139,44 @@ class _HomeViewState extends State { return _error.isNotEmpty ? StatusCard(message: _error, success: false) - : Column(children: [ - ListTile( - title: Text( - "Events", - style: textTheme.headline5, - )), - Expanded( - child: ListView.separated( - itemCount: _events.length, - itemBuilder: (context, index) { - return ListTile( - title: Row(children: [ - Padding( - padding: const EdgeInsets.only(right: 8), - child: Text(_events[index].name), - ), - Chip( - label: _events[index].status == true - ? const Text("open") - : const Text("closed"), - backgroundColor: _events[index].status == true - ? Colors.green.shade500 - : Colors.red.shade500, - ) - ]), - subtitle: Text(_events[index].description ?? ""), - enabled: _events[index].status == true, - onTap: () { - // go to event page - print("event pressed ${_events[index].name}"); - }, - ); + : SingleChildScrollView( + child: ListViewCard(labelText: "Events", children: [ + ListView.separated( + shrinkWrap: true, + physics: const ClampingScrollPhysics(), + itemCount: _events.length, + itemBuilder: (context, index) { + return ListTile( + title: Row(children: [ + Padding( + padding: const EdgeInsets.only(right: 8), + child: Text(_events[index].name), + ), + Chip( + label: _events[index].status == true + ? const Text("open") + : const Text("closed"), + backgroundColor: _events[index].status == true + ? Colors.green.shade500 + : Colors.red.shade500, + ) + ]), + subtitle: Text(_events[index].description ?? ""), + enabled: _events[index].status == true, + trailing: _events[index].status == true + ? const Icon(Icons.chevron_right) + : null, + onTap: () { + // go to event page + // TODO: implement + print("event pressed ${_events[index].name}"); }, - separatorBuilder: (context, index) { - return const Divider(); - })) - ]); + ); + }, + separatorBuilder: (context, index) { + return const Divider(); + }) + ])); } getUserInfo(Function(Status) callback) async { diff --git a/lib/view/settings.view.dart b/lib/view/settings.view.dart index 611cea0..8f68cdb 100644 --- a/lib/view/settings.view.dart +++ b/lib/view/settings.view.dart @@ -1,17 +1,161 @@ +import 'package:amplify_flutter/amplify_flutter.dart'; import 'package:flutter/material.dart'; +import 'package:hacklytics_checkin_flutter/components/HeadingListTile.component.dart'; +import 'package:hacklytics_checkin_flutter/components/ListViewCard.component.dart'; +import 'package:hacklytics_checkin_flutter/components/toast.component.dart'; +import 'package:hacklytics_checkin_flutter/main.dart'; +import 'package:hacklytics_checkin_flutter/model/amplifyuser.dart'; +import 'package:package_info_plus/package_info_plus.dart'; +import 'package:flutter/services.dart'; +import 'package:fluttertoast/fluttertoast.dart'; -class SettingsView extends StatelessWidget { - const SettingsView({super.key}); +class SettingsView extends StatefulWidget { + const SettingsView({required this.user, super.key}); + + final AmplifyUser user; + + @override + State createState() => _SettingsViewState(); +} + +class _SettingsViewState extends State { + bool _loadingVersion = true; + late PackageInfo _packageInfo; + + late FToast ftoast; @override Widget build(BuildContext context) { + if (_loadingVersion) { + PackageInfo.fromPlatform().then((value) { + setState(() { + _packageInfo = value; + _loadingVersion = false; + }); + }); + } + return Scaffold( - appBar: AppBar( - title: const Text("Settings"), - ), - body: const Center( - child: Text("Settings"), - ), + key: globalKey, + appBar: AppBar( + title: const Text("Settings"), + ), + body: _buildWithVersionInfo(context)); + } + + _buildWithVersionInfo(BuildContext context) { + return _loadingVersion + ? const Center(child: CircularProgressIndicator()) + : _buildBody(context); + } + + _buildBody(BuildContext context) { + ftoast = FToast(); + ftoast.init(globalKey.currentState!.context); + return SingleChildScrollView( + child: Column( + children: [ + // const HeadingListTile(labelText: "App Info"), + // const Divider(), + ListViewCard(labelText: "App Info", children: [ + ListTile( + title: const Text("App Name"), + subtitle: Text(_packageInfo.appName), + onLongPress: () { + _copyToClipboard(_packageInfo.appName); + }, + ), + const Divider(), + ListTile( + title: const Text("Package Name"), + subtitle: Text(_packageInfo.packageName), + onLongPress: () { + _copyToClipboard(_packageInfo.packageName); + }, + ), + const Divider(), + ListTile( + title: const Text("Version"), + subtitle: Text(_packageInfo.version), + onLongPress: () { + _copyToClipboard(_packageInfo.version); + }, + ), + const Divider(), + ListTile( + title: const Text("Build Number"), + subtitle: Text(_packageInfo.buildNumber), + onLongPress: () { + _copyToClipboard(_packageInfo.buildNumber); + }, + ), + const Divider(), + ListTile( + title: const Text("Build Signature"), + subtitle: Text(_packageInfo.buildSignature), + onLongPress: () { + _copyToClipboard(_packageInfo.buildSignature); + }, + ), + ]), + + // const HeadingListTile(labelText: "User Info"), + // // const Divider(), + ListViewCard(labelText: "User Info", children: [ + ListTile( + title: const Text("Group(s)"), + subtitle: Text(widget.user.groups.join(", ")), + onLongPress: () { + _copyToClipboard(widget.user.groups.join(", ")); + }, + ), + const Divider(), + _userAttributesMap() + ]) + ], + )); + } + + _copyToClipboard(String text) { + Clipboard.setData(ClipboardData(text: text)); + // show toast + ftoast.showToast( + child: const ConfirmToast(labelText: "Copied to clipboard"), + gravity: ToastGravity.BOTTOM, + toastDuration: const Duration(seconds: 2), ); } + + _userAttributesMap() { + return ListView.separated( + shrinkWrap: true, + physics: const ClampingScrollPhysics(), + itemBuilder: (context, index) { + var a = widget.user.attributes[index]; + return ListTile( + title: Text(a.userAttributeKey.key.capitalize()), + subtitle: Text(a.value), + onLongPress: () { + _copyToClipboard(a.value); + }, + ); + }, + separatorBuilder: ((context, index) { + return const Divider(); + }), + itemCount: widget.user.attributes.length); + // widget.user.attributes.map((e) => ListTile( + // title: Text(e.userAttributeKey.key.capitalize()), + // subtitle: Text(e.value), + // onLongPress: () { + // _copyToClipboard(e.value); + // }, + // )); + } +} + +extension StringExtension on String { + String capitalize() { + return "${this[0].toUpperCase()}${this.substring(1).toLowerCase()}"; + } } diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index cccf817..08d9c9c 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,6 +5,8 @@ import FlutterMacOS import Foundation +import package_info_plus_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin")) } diff --git a/pubspec.lock b/pubspec.lock index 598b71a..329a085 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -218,6 +218,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" file: dependency: transitive description: @@ -254,6 +261,18 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + fluttertoast: + dependency: "direct main" + description: + name: fluttertoast + url: "https://pub.dartlang.org" + source: hosted + version: "8.1.1" frontend_server_client: dependency: transitive description: @@ -316,7 +335,7 @@ packages: name: js url: "https://pub.dartlang.org" source: hosted - version: "0.6.5" + version: "0.6.4" json_annotation: dependency: transitive description: @@ -394,6 +413,48 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + package_info_plus: + dependency: "direct main" + description: + name: package_info_plus + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.3+1" + package_info_plus_linux: + dependency: transitive + description: + name: package_info_plus_linux + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.5" + package_info_plus_macos: + dependency: transitive + description: + name: package_info_plus_macos + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + package_info_plus_platform_interface: + dependency: transitive + description: + name: package_info_plus_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" + package_info_plus_web: + dependency: transitive + description: + name: package_info_plus_web + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.6" + package_info_plus_windows: + dependency: transitive + description: + name: package_info_plus_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" path: dependency: transitive description: @@ -637,6 +698,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.0" + win32: + dependency: transitive + description: + name: win32 + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.2" xml: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index c660d92..01bd029 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.0.30 +version: 1.0.31 environment: sdk: '>=2.18.5 <3.0.0' @@ -44,6 +44,8 @@ dependencies: nfc_manager: ^3.2.0 provider: badges: ^2.0.3 + package_info_plus: ^1.0.6 + fluttertoast: ^8.1.1 dev_dependencies: flutter_test: