diff --git a/.drone.yml b/.drone.yml index 45fc462b..f84cb7b9 100644 --- a/.drone.yml +++ b/.drone.yml @@ -24,7 +24,7 @@ steps: - git checkout $DRONE_COMMIT - name: fetch - image: cirrusci/flutter:dev + image: cirrusci/flutter:2.5.0-6.0.pre volumes: - name: deps path: /root/.pub-cache @@ -47,7 +47,7 @@ steps: # #Todo: fix all the lint errors and add `-set_exit_status` above to enforce linting - name: build-linux - image: openpriv/flutter-desktop:linux-dev + image: openpriv/flutter-desktop:linux-fdev2.5rc volumes: - name: deps path: /root/.pub-cache @@ -61,7 +61,7 @@ steps: - rm -r cwtch - name: test-build-android - image: cirrusci/flutter:dev + image: cirrusci/flutter:2.5.0-6.0.pre when: event: pull_request volumes: @@ -71,7 +71,7 @@ steps: - flutter build apk --debug - name: build-android - image: cirrusci/flutter:dev + image: cirrusci/flutter:2.5.0-6.0.pre when: event: push environment: @@ -95,7 +95,7 @@ steps: #- cp build/app/outputs/flutter-apk/app-debug.apk deploy/android - name: widget-tests - image: cirrusci/flutter:dev + image: cirrusci/flutter:2.5.0-6.0.pre volumes: - name: deps path: /root/.pub-cache @@ -126,7 +126,7 @@ steps: - mv ./../sha256s.txt . - cd .. # TODO: do deployment once files actaully compile - - scp -r -o StrictHostKeyChecking=no -i ~/id_rsa $DIR buildfiles@openprivacy.ca:/home/buildfiles/buildfiles/ + - scp -r -o StrictHostKeyChecking=no -i ~/id_rsa $DIR buildfiles@build.openprivacy.ca:/home/buildfiles/buildfiles/ - name: notify-email image: drillster/drone-email @@ -175,7 +175,7 @@ clone: steps: - name: clone - image: openpriv/flutter-desktop:windows-sdk30-fdev2.3rc + image: openpriv/flutter-desktop:windows-sdk30-fdev2.5rc environment: buildbot_key_b64: from_secret: buildbot_key_b64 @@ -193,16 +193,16 @@ steps: - git checkout $Env:DRONE_COMMIT - name: fetch - image: openpriv/flutter-desktop:windows-sdk30-fdev2.3rc + image: openpriv/flutter-desktop:windows-sdk30-fdev2.5rc commands: - - powershell -command "Invoke-WebRequest -Uri https://dist.torproject.org/torbrowser/10.5a17/tor-win64-0.4.6.5.zip -OutFile tor.zip" + - powershell -command "Invoke-WebRequest -Uri https://git.openprivacy.ca/openprivacy/buildfiles/raw/branch/master/tor/tor-win64-0.4.6.5.zip -OutFile tor.zip" - powershell -command "if ((Get-FileHash tor.zip -Algorithm sha512).Hash -ne '7917561a7a063440a1ddfa9cb544ab9ffd09de84cea3dd66e3cc9cd349dd9f85b74a522ec390d7a974bc19b424c4d53af60e57bbc47e763d13cab6a203c4592f' ) { Write-Error 'tor.zip sha512sum mismatch' }" - git describe --tags --abbrev=1 > VERSION - powershell -command "Get-Date -Format 'yyyy-MM-dd-HH-mm'" > BUILDDATE - .\fetch-libcwtch-go.ps1 - name: build-windows - image: openpriv/flutter-desktop:windows-sdk30-fdev2.3rc + image: openpriv/flutter-desktop:windows-sdk30-fdev2.5rc commands: - flutter pub get - $Env:version += type .\VERSION @@ -213,9 +213,9 @@ steps: # flutter hasn't worked out it's packaging of required dll's so we have to resort to this manual nonsense # https://github.com/google/flutter-desktop-embedding/issues/587 # https://github.com/flutter/flutter/issues/53167 - - copy C:\BuildTools\VC\Redist\MSVC\14.29.30036\x64\Microsoft.VC142.CRT\vcruntime140.dll $Env:releasedir - - copy C:\BuildTools\VC\Redist\MSVC\14.29.30036\x64\Microsoft.VC142.CRT\vcruntime140_1.dll $Env:releasedir - - copy C:\BuildTools\VC\Redist\MSVC\14.29.30036\x64\Microsoft.VC142.CRT\msvcp140.dll $Env:releasedir + - copy C:\BuildTools\VC\Redist\MSVC\14.29.30133\x64\Microsoft.VC142.CRT\vcruntime140.dll $Env:releasedir + - copy C:\BuildTools\VC\Redist\MSVC\14.29.30133\x64\Microsoft.VC142.CRT\vcruntime140_1.dll $Env:releasedir + - copy C:\BuildTools\VC\Redist\MSVC\14.29.30133\x64\Microsoft.VC142.CRT\msvcp140.dll $Env:releasedir - copy README.md $Env:releasedir\ - copy windows\*.bat $Env:releasedir\ - powershell -command "Expand-Archive -Path tor.zip -DestinationPath $Env:releasedir\Tor" @@ -258,7 +258,7 @@ steps: - move *.sha512 deploy\$Env:builddir - name: deploy-windows - image: openpriv/flutter-desktop:windows-sdk30-fdev2.3rc + image: openpriv/flutter-desktop:windows-sdk30-fdev2.5rc when: event: push status: [ success ] @@ -268,7 +268,7 @@ steps: commands: - echo $Env:BUILDFILES_KEY > id_rsab64 - certutil -decode id_rsab64 id_rsa - - scp -r -o StrictHostKeyChecking=no -i id_rsa deploy\\* buildfiles@openprivacy.ca:/home/buildfiles/buildfiles/ + - scp -r -o StrictHostKeyChecking=no -i id_rsa deploy\\* buildfiles@build.openprivacy.ca:/home/buildfiles/buildfiles/ trigger: repo: cwtch.im/cwtch-ui diff --git a/lib/main.dart b/lib/main.dart index 9a6e7d55..6fd9eebc 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -169,7 +169,7 @@ class FlwtchState extends State { var args = jsonDecode(call.arguments); var profile = profs.getProfile(args["ProfileOnion"])!; var convo = profile.contactList.getContact(args["Handle"])!; - var initialIndex = convo.unreadMessages; + Provider.of(navKey.currentContext!, listen: false).initialScrollIndex = convo.unreadMessages; convo.unreadMessages = 0; // single pane mode pushes; double pane mode reads AppState.selectedProfile/Conversation @@ -187,7 +187,7 @@ class FlwtchState extends State { ChangeNotifierProvider.value(value: profile), ChangeNotifierProvider.value(value: convo), ], - builder: (context, child) => MessageView(initialIndex), + builder: (context, child) => MessageView(), ); }, ), diff --git a/lib/model.dart b/lib/model.dart index 39fe3e3a..75b39197 100644 --- a/lib/model.dart +++ b/lib/model.dart @@ -30,6 +30,7 @@ class AppState extends ChangeNotifier { String appError = ""; String? _selectedProfile; String? _selectedConversation; + int _initialScrollIndex = 0; int? _selectedIndex; bool _unreadMessagesBelow = false; @@ -67,6 +68,12 @@ class AppState extends ChangeNotifier { notifyListeners(); } + int get initialScrollIndex => _initialScrollIndex; + set initialScrollIndex(int newVal) { + this._initialScrollIndex = newVal; + notifyListeners(); + } + bool isLandscape(BuildContext c) => MediaQuery.of(c).size.width > MediaQuery.of(c).size.height; } diff --git a/lib/views/contactsview.dart b/lib/views/contactsview.dart index dbb59909..5bd3897d 100644 --- a/lib/views/contactsview.dart +++ b/lib/views/contactsview.dart @@ -23,18 +23,19 @@ class ContactsView extends StatefulWidget { // selectConversation can be called from anywhere to set the active conversation void selectConversation(BuildContext context, String handle) { - var initialIndex = Provider.of(context, listen: false).contactList.getContact(handle)!.unreadMessages; // requery instead of using contactinfostate directly because sometimes listview gets confused about data that resorts + var initialIndex = Provider.of(context, listen: false).contactList.getContact(handle)!.unreadMessages; Provider.of(context, listen: false).contactList.getContact(handle)!.unreadMessages = 0; // triggers update in Double/TripleColumnView + Provider.of(context, listen: false).initialScrollIndex = initialIndex; Provider.of(context, listen: false).selectedConversation = handle; Provider.of(context, listen: false).selectedIndex = null; // if in singlepane mode, push to the stack var isLandscape = Provider.of(context, listen: false).isLandscape(context); - if (Provider.of(context, listen: false).uiColumns(isLandscape).length == 1) _pushMessageView(context, handle, initialIndex); + if (Provider.of(context, listen: false).uiColumns(isLandscape).length == 1) _pushMessageView(context, handle); } -void _pushMessageView(BuildContext context, String handle, int initialIndex) { +void _pushMessageView(BuildContext context, String handle) { var profileOnion = Provider.of(context, listen: false).onion; Navigator.of(context).push( MaterialPageRoute( @@ -47,7 +48,7 @@ void _pushMessageView(BuildContext context, String handle, int initialIndex) { ChangeNotifierProvider.value(value: profile), ChangeNotifierProvider.value(value: profile.contactList.getContact(handle)!), ], - builder: (context, child) => MessageView(initialIndex), + builder: (context, child) => MessageView(), ); }, ), diff --git a/lib/views/doublecolview.dart b/lib/views/doublecolview.dart index 9e163b74..ebd7ffff 100644 --- a/lib/views/doublecolview.dart +++ b/lib/views/doublecolview.dart @@ -17,7 +17,6 @@ class _DoubleColumnViewState extends State { Widget build(BuildContext context) { var flwtch = Provider.of(context); var cols = Provider.of(context).uiColumns(true); - var initialIndex = flwtch.selectedConversation == null ? 0 : Provider.of(context, listen: false).contactList.getContact(flwtch.selectedConversation!)!.unreadMessages; return Flex( direction: Axis.horizontal, children: [ @@ -36,7 +35,7 @@ class _DoubleColumnViewState extends State { ChangeNotifierProvider.value(value: Provider.of(context)), ChangeNotifierProvider.value( value: flwtch.selectedConversation != null ? Provider.of(context).contactList.getContact(flwtch.selectedConversation!)! : ContactInfoState("", "")), - ], child: Container(child: MessageView(initialIndex))), + ], child: Container(child: MessageView())), ), ], ); diff --git a/lib/views/messageview.dart b/lib/views/messageview.dart index 9bb44d31..8ee6196c 100644 --- a/lib/views/messageview.dart +++ b/lib/views/messageview.dart @@ -22,9 +22,6 @@ import '../widgets/messagelist.dart'; import 'groupsettingsview.dart'; class MessageView extends StatefulWidget { - int initialIndex; - MessageView(this.initialIndex); - @override _MessageViewState createState() => _MessageViewState(); } @@ -38,24 +35,31 @@ class _MessageViewState extends State { @override void initState() { - // using "8" because "# of messages that fit on one screen" isnt trivial to calculate at this point - if (widget.initialIndex > 8) { - WidgetsFlutterBinding.ensureInitialized().addPostFrameCallback((timeStamp) { - Provider.of(context, listen: false).unreadMessagesBelow = true; - }); - } - scrollListener.itemPositions.addListener(() { var first = scrollListener.itemPositions.value.first.index; var last = scrollListener.itemPositions.value.last.index; // sometimes these go hi->lo and sometimes they go lo->hi because [who tf knows] - if (first == 0 || last == 0) { + if ((first == 0 || last == 0) && Provider.of(context, listen: false).unreadMessagesBelow == true) { + Provider.of(context, listen: false).initialScrollIndex = 0; Provider.of(context, listen: false).unreadMessagesBelow = false; } }); super.initState(); } + @override + void didChangeDependencies() { + var appState = Provider.of(context, listen: false); + + // using "8" because "# of messages that fit on one screen" isnt trivial to calculate at this point + if (appState.initialScrollIndex > 8 && appState.unreadMessagesBelow == false) { + WidgetsFlutterBinding.ensureInitialized().addPostFrameCallback((timeStamp) { + appState.unreadMessagesBelow = true; + }); + } + super.didChangeDependencies(); + } + @override void dispose() { focusNode.dispose(); @@ -107,7 +111,7 @@ class _MessageViewState extends State { onPressed: _pushContactSettings), ], ), - body: Padding(padding: EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 108.0), child: MessageList(widget.initialIndex, scrollController, scrollListener)), + body: Padding(padding: EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 108.0), child: MessageList(scrollController, scrollListener)), bottomSheet: _buildComposeBox(), )); } diff --git a/lib/views/triplecolview.dart b/lib/views/triplecolview.dart index b666e9b1..4156c738 100644 --- a/lib/views/triplecolview.dart +++ b/lib/views/triplecolview.dart @@ -35,7 +35,7 @@ class _TripleColumnViewState extends State { child: appState.selectedConversation == null ? Center(child: Text(AppLocalizations.of(context)!.addContactFirst)) : //dev - Container(child: MessageView(0/*todo:setme*/)), + Container(child: MessageView()), ), ]); } diff --git a/lib/widgets/contactrow.dart b/lib/widgets/contactrow.dart index 18c750dc..140e3703 100644 --- a/lib/widgets/contactrow.dart +++ b/lib/widgets/contactrow.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:cwtch/views/contactsview.dart'; import 'package:flutter/material.dart'; import 'package:flutter/painting.dart'; @@ -127,9 +129,9 @@ class _ContactRowState extends State { } // If the last message was over a day ago, just state the date if (DateTime.now().difference(date).inDays > 1) { - return DateFormat.yMd().format(date.toLocal()); + return DateFormat.yMd(Platform.localeName).format(date.toLocal()); } // Otherwise just state the time. - return DateFormat.Hm().format(date.toLocal()); + return DateFormat.Hm(Platform.localeName).format(date.toLocal()); } } diff --git a/lib/widgets/invitationbubble.dart b/lib/widgets/invitationbubble.dart index 4770283d..9214fd69 100644 --- a/lib/widgets/invitationbubble.dart +++ b/lib/widgets/invitationbubble.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:io'; import 'package:cwtch/cwtch_icons_icons.dart'; import 'package:cwtch/models/message.dart'; @@ -39,7 +40,7 @@ class InvitationBubbleState extends State { var borderRadiousEh = 15.0; var showGroupInvite = Provider.of(context).isExperimentEnabled(TapirGroupsExperiment); rejected = Provider.of(context).flags & 0x01 == 0x01; - var prettyDate = DateFormat.yMd().add_jm().format(Provider.of(context).timestamp); + var prettyDate = DateFormat.yMd(Platform.localeName).add_jm().format(Provider.of(context).timestamp); // If the sender is not us, then we want to give them a nickname... var senderDisplayStr = ""; diff --git a/lib/widgets/messagebubble.dart b/lib/widgets/messagebubble.dart index 094e0ff9..2ba8fe0c 100644 --- a/lib/widgets/messagebubble.dart +++ b/lib/widgets/messagebubble.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:cwtch/models/message.dart'; import 'package:cwtch/widgets/malformedbubble.dart'; import 'package:flutter/material.dart'; @@ -28,7 +30,7 @@ class MessageBubbleState extends State { // var myKey = Provider.of(context).profileOnion + "::" + Provider.of(context).contactHandle + "::" + Provider.of(context).messageIndex.toString(); DateTime messageDate = Provider.of(context).timestamp; - prettyDate = DateFormat.yMd().add_jm().format(messageDate.toLocal()); + prettyDate = DateFormat.yMd(Platform.localeName).add_jm().format(messageDate.toLocal()); // If the sender is not us, then we want to give them a nickname... var senderDisplayStr = ""; diff --git a/lib/widgets/messagelist.dart b/lib/widgets/messagelist.dart index defa3a19..e6f8ab64 100644 --- a/lib/widgets/messagelist.dart +++ b/lib/widgets/messagelist.dart @@ -9,10 +9,9 @@ import '../model.dart'; import '../settings.dart'; class MessageList extends StatefulWidget { - int initialIndex; ItemScrollController scrollController; ItemPositionsListener scrollListener; - MessageList(this.initialIndex, this.scrollController, this.scrollListener); + MessageList(this.scrollController, this.scrollListener); @override _MessageListState createState() => _MessageListState(); @@ -21,6 +20,7 @@ class MessageList extends StatefulWidget { class _MessageListState extends State { @override Widget build(BuildContext outerContext) { + var initi = Provider.of(outerContext, listen: false).initialScrollIndex; bool isP2P = !Provider.of(context).isGroup; bool isGroupAndSyncing = Provider.of(context).isGroup == true && Provider.of(context).status == "Authenticated"; bool isGroupAndSynced = Provider.of(context).isGroup && Provider.of(context).status == "Synced"; @@ -72,7 +72,7 @@ class _MessageListState extends State { ? ScrollablePositionedList.builder( itemPositionsListener: widget.scrollListener, itemScrollController: widget.scrollController, - initialScrollIndex: widget.initialIndex, + initialScrollIndex: Provider.of(outerContext, listen: false).initialScrollIndex, itemCount: Provider.of(outerContext).totalMessages, reverse: true, // NOTE: There seems to be a bug in flutter that corrects the mouse wheel scroll, but not the drag direction... itemBuilder: (itemBuilderContext, index) { diff --git a/pubspec.lock b/pubspec.lock index 2ee3b476..b8117b89 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -21,7 +21,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.7.0" + version: "2.8.1" boolean_selector: dependency: transitive description: @@ -181,7 +181,7 @@ packages: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.4.0" + version: "1.7.0" msix: dependency: "direct dev" description: @@ -329,6 +329,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "5.0.0" + scrollable_positioned_list: + dependency: "direct main" + description: + name: scrollable_positioned_list + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.0-nullsafety.0" sky_engine: dependency: transitive description: flutter @@ -375,7 +382,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.1" + version: "0.4.2" typed_data: dependency: transitive description: