-
-
Notifications
You must be signed in to change notification settings - Fork 22
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
New Room Preview facilities #2373
base: main
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2373 +/- ##
==========================================
- Coverage 28.88% 28.84% -0.04%
==========================================
Files 680 695 +15
Lines 45422 46083 +661
==========================================
+ Hits 13119 13292 +173
- Misses 32303 32791 +488
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
36036c8
to
81944e0
Compare
enum ErrorCode { | ||
notFound, | ||
forbidden, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extended the Error types to be more specific and more precise and allow us to show a different error depending on the underlying code we were given by the server: most notably if we were forbidden access.
error: error, | ||
stack: stack, | ||
textBuilder: (error, errCode) => switch (errCode) { | ||
ErrorCode.forbidden => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Showing different errors depending on the error indicated by the server.
@@ -113,6 +113,10 @@ List<String> asDartStringList(FfiListFfiString data) { | |||
return data.toList().map((e) => e.toDartString()).toList(); | |||
} | |||
|
|||
extension FfiListFfiStringtoDart on FfiListFfiString { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
made this more accessible via helper extension
@@ -167,7 +169,7 @@ class SubChatsPage extends ConsumerWidget { | |||
[]; | |||
final remoteSubchats = | |||
ref.watch(remoteChatRelationsProvider(spaceId)).valueOrNull ?? []; | |||
final entries = []; | |||
final List<(SpaceHierarchyRoomInfo?, String)> entries = []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
being specific in types allows the dart compiler to figure out the type below isn't correct.
import 'package:flutter/material.dart'; | ||
import 'package:phosphor_flutter/phosphor_flutter.dart'; | ||
|
||
class ItemPreviewCard extends StatelessWidget { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generic type that can render an item preview, as used internally by the ref-details or the uri-parsing entity
String? server, | ||
Function(String)? forward, | ||
) async { | ||
Future<String?> joinRoom({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Several fixes and refactors in this one:
- replace that bad old pattern of having a forward-function passed with a proper future based returning instead
- allow to throw the error or return an null on failure
- support for more than one via-server as the API now allows for that, too
- fix the check of the room actually being available and accessible
final isSpace = await _ensureLoadedWithinTime(() async { | ||
final room = await ref.refresh(maybeRoomProvider(roomId).future); | ||
return room?.isJoined() == true ? room!.isSpace() : null; | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this now properly checks for the room being available and accessible to the UI before continuing.
); | ||
} | ||
|
||
Widget buildPreview(BuildContext context) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
new feature to show the preview in the chat for a room we don't have access to
shareContentBuilder: shareContentBuilder, | ||
); | ||
} | ||
|
||
Widget? qrCodeHeader(BuildContext context) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor feature (and useful for debugging): show the to be shared information within the QRcode above the QRcode as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tests updated for additional via
-support that we always include now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice addition!!
Added few comments few none of that blocking for merge. PR changes looks good to me.
class AllHashed<T> { | ||
final List<T> items; | ||
|
||
AllHashed(this.items); | ||
|
||
@override | ||
int get hashCode => Object.hashAll(items); | ||
|
||
@override | ||
bool operator ==(Object other) { | ||
if (other is AllHashed<T>) { | ||
return items == other.items; | ||
} else if (other is List<T>) { | ||
return items == other; | ||
} | ||
return false; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not understanding this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
two list of items, even if they are all the same, will come out as "different" if they are different instances. This is used to ensure that https://github.com/acterglobal/a3/pull/2373/files#diff-b2a403334550e3f97cc376cf1228271526121ca2ecf70cf62e6c50ba41e69289R14 caches the input value and not keeps triggering for every render.
} else if (errorStr.contains('[400 / UNKNOWN]')) { | ||
return ErrorCode.unknown; | ||
} else if (errorStr.contains('[403 / M_FORBIDDEN]')) { | ||
return ErrorCode.forbidden; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
errorStr
will contains exact [400 / UNKNOWN]
?
If not then how about making condition like if (errorStr.contains('400') || errorStr.contains('UNKNOWN'))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, this is exact on purpose.
ObjectType? finalType() { | ||
ObjectRef? cur = objectPath; | ||
while (cur?.child != null) { | ||
cur = cur?.child; // find the deepest object | ||
} | ||
return cur?.objectType; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not understanding this code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it traverses the object path of the reference type to give the most internal objects type.
the way this is constructed is that the actor URI allows unlimited deep linking. Think:
/tl/asdf/t/339390/c/2323
-> this is a reference to the comment 2323
of task 33930
of task list asdf
. The way this is represented in the parse uri result is that every object with an object path can have an additional child
which (going left to right) gives the next inner type. So this would be TaskList[id=asdf, child=Task[id=339390. child=Comment[id=2323]]]
. In order to find out what the actual final object is (in this case "comment"), you need to traverse that tree. Which is what this code does: look for the most inner item that doesn't have any child (in the while
) and then return its objectType.
headerInfo: Column( | ||
crossAxisAlignment: CrossAxisAlignment.start, | ||
children: [ | ||
Padding( | ||
padding: EdgeInsets.symmetric(vertical: 8), | ||
child: Text( | ||
L10n.of(context).toAccess, | ||
style: Theme.of(context).textTheme.bodyMedium, | ||
), | ||
), | ||
ItemPreviewCard( | ||
// showing the same item without the tap | ||
title: refDetails.title(), | ||
refType: typeFromRefDetails(refDetails), | ||
), | ||
Padding( | ||
padding: EdgeInsets.symmetric(vertical: 8), | ||
child: Text( | ||
L10n.of(context).needToBeMemberOf, | ||
style: Theme.of(context).textTheme.bodyMedium, | ||
), | ||
), | ||
], | ||
), | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably we can design better design for this. (Later part..)
Also can be generalised this code as I see this used couple of times..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is already generalized some part. But I didn't get this much further without making things a lot more specific again ... Happy to go further though.
final bool tapEnabled; | ||
final EdgeInsets? margin; | ||
|
||
const ReferenceDetailsItem({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the need of ReferenceDetailsItem
as we have ItemPreviewCard
. Can't we combined those in single widget?
Widget roomHeader(RoomPreview preview) => Consumer( | ||
builder: (context, ref, child) => ListTile( | ||
leading: ActerAvatar( | ||
options: AvatarOptions(ref.watch(roomPreviewAvatarInfo(query))), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't understand this query
thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
query needs roomId and via-server listing, which is combined as query
record.
try { | ||
final res = await callback(); | ||
if (res != null) { | ||
return res; | ||
} | ||
} catch (e) { | ||
if (throwError) rethrow; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't understand need of this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this code was meant to repeatedly try to call the function until a timeout occured. But that wasn't the case if there was an exception raised in the inner code, it would just fail immediately instead of retrying. This fixes the retry behaviour to what we really wanted to have in the first place.
You will now get the room preview shown (if the server supports it), with the ability to join the space, if you have the permissions to,
When you click on an Space / Chat Invite
preview-on-invite.mp4
When you try to access an object via Ref you don't have access to yet
unknown-object-via-boost.mp4
When you scan a QR code to an object you aren't in the space of yet
screen-20250119-125254.mp4
For additional convienience, we are also showing exactly what will be seen/shown/shared over the QR code to the other user, too:
To the reviewer:
Sorry, for again coming with such a large pull request. But in certain parts of the app (especially with really old code, like this joining rooms one), it's like the famous "pulling one thread and the entire thing unravels" ... and cascading changes are needed.
In particular these are (not the order they were committed):
textBuilder
-changes on thoseActerError
-Widget in db8e099joinRoom
-action to remove the forwarding-callback and instead use the future-syntax as we do in other actions as well, in f2036f9