kopia lustrzana https://gitlab.com/mysocialportal/relatica
Merge branch 'timeline-and-post-tweaks' into 'contacts-update'
Timeline and post tweaks See merge request mysocialportal/friendica_portal!1codemagic-setup
commit
fbab2dcae1
|
@ -1,6 +1,6 @@
|
|||
PODS:
|
||||
- Flutter (1.0.0)
|
||||
- flutter_secure_storage (6.0.0):
|
||||
- flutter_secure_storage (3.3.1):
|
||||
- Flutter
|
||||
- FMDB (2.7.5):
|
||||
- FMDB/standard (= 2.7.5)
|
||||
|
@ -43,7 +43,7 @@ EXTERNAL SOURCES:
|
|||
|
||||
SPEC CHECKSUMS:
|
||||
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
||||
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
|
||||
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
|
||||
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
||||
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
|
||||
shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad
|
||||
|
|
|
@ -55,14 +55,16 @@ class _StatusControlState extends State<StatusControl> {
|
|||
@override
|
||||
void initState() {
|
||||
showContent = entry.spoilerText.isEmpty;
|
||||
showComments = isPost ? false : true;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final manager = context.watch<TimelineManager>();
|
||||
_logger.finest('Building ${item.entry.toShortString()}');
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
final padding = isPost ? 8.0 : 8.0;
|
||||
final body = Padding(
|
||||
padding: EdgeInsets.all(padding),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
@ -119,6 +121,10 @@ class _StatusControlState extends State<StatusControl> {
|
|||
],
|
||||
),
|
||||
);
|
||||
|
||||
return isPost
|
||||
? body
|
||||
: Card(color: Theme.of(context).splashColor, child: body);
|
||||
}
|
||||
|
||||
Widget buildHeader(BuildContext context) {
|
||||
|
@ -184,7 +190,6 @@ class _StatusControlState extends State<StatusControl> {
|
|||
return const SizedBox();
|
||||
}
|
||||
return SizedBox(
|
||||
width: 250.0,
|
||||
height: 250.0,
|
||||
child: ListView.separated(
|
||||
scrollDirection: Axis.horizontal,
|
||||
|
@ -235,16 +240,16 @@ class _StatusControlState extends State<StatusControl> {
|
|||
|
||||
Widget buildChildComments(BuildContext context) {
|
||||
final comments = widget.originalItem.children;
|
||||
|
||||
if (comments.isEmpty) {
|
||||
return Text('No comments');
|
||||
}
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(left: 20.0, top: 5.0),
|
||||
padding: EdgeInsets.only(left: 5.0, top: 5.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Icon(Icons.subdirectory_arrow_right),
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: comments
|
||||
|
|
|
@ -229,7 +229,7 @@ class FriendicaClient {
|
|||
return (await runCatchingAsync(() async {
|
||||
final baseUrl = 'https://$serverName/api/v1/statuses/$id';
|
||||
final url = fullContext ? '$baseUrl/context' : baseUrl;
|
||||
final request = Uri.parse(url);
|
||||
final request = Uri.parse('$url?limit=1000');
|
||||
_logger.finest(() =>
|
||||
'Getting entry for status $id, full context? $fullContext : $url');
|
||||
return (await _getApiRequest(request).andThenSuccessAsync((json) async {
|
||||
|
@ -472,7 +472,8 @@ class FriendicaClient {
|
|||
case TimelineType.profile:
|
||||
return '/accounts/${type.auxData}/statuses';
|
||||
case TimelineType.self:
|
||||
throw UnimplementedError('These types are not supported yet');
|
||||
final myId = getIt<AuthService>().currentId;
|
||||
return '/accounts/$myId/statuses';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -482,11 +483,10 @@ class FriendicaClient {
|
|||
case TimelineType.global:
|
||||
case TimelineType.profile:
|
||||
case TimelineType.group:
|
||||
case TimelineType.self:
|
||||
return '';
|
||||
case TimelineType.local:
|
||||
return 'local=true';
|
||||
case TimelineType.self:
|
||||
throw UnimplementedError('These types are not supported yet');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ enum TimelineType {
|
|||
case TimelineType.profile:
|
||||
return 'Profile';
|
||||
case TimelineType.self:
|
||||
return 'Self';
|
||||
return 'Yours';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,8 +37,7 @@ class TimelineIdentifiers {
|
|||
factory TimelineIdentifiers.home() =>
|
||||
TimelineIdentifiers(timeline: TimelineType.home);
|
||||
|
||||
factory TimelineIdentifiers.profile(String profileId) =>
|
||||
TimelineIdentifiers(
|
||||
factory TimelineIdentifiers.profile(String profileId) => TimelineIdentifiers(
|
||||
timeline: TimelineType.profile,
|
||||
auxData: profileId,
|
||||
);
|
||||
|
@ -53,10 +52,10 @@ class TimelineIdentifiers {
|
|||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is TimelineIdentifiers &&
|
||||
runtimeType == other.runtimeType &&
|
||||
timeline == other.timeline &&
|
||||
auxData == other.auxData;
|
||||
other is TimelineIdentifiers &&
|
||||
runtimeType == other.runtimeType &&
|
||||
timeline == other.timeline &&
|
||||
auxData == other.auxData;
|
||||
|
||||
@override
|
||||
int get hashCode => timeline.hashCode ^ auxData.hashCode;
|
||||
|
|
|
@ -5,7 +5,7 @@ class Timeline {
|
|||
final TimelineIdentifiers id;
|
||||
final List<EntryTreeItem> _posts = [];
|
||||
final Map<String, EntryTreeItem> _postsById = {};
|
||||
int _lowestStatusId = 0;
|
||||
int _lowestStatusId = 9223372036854775807;
|
||||
int _highestStatusId = 0;
|
||||
|
||||
int get highestStatusId => _highestStatusId;
|
||||
|
@ -44,7 +44,7 @@ class Timeline {
|
|||
final parentId = comment.entry.parentId;
|
||||
for (final p in _posts) {
|
||||
final parent =
|
||||
p.id == parentId ? p : p.getChildById(comment.entry.parentId);
|
||||
p.id == parentId ? p : p.getChildById(comment.entry.parentId);
|
||||
if (parent != null) {
|
||||
parent.addOrUpdate(comment);
|
||||
changed = true;
|
||||
|
@ -64,8 +64,7 @@ class Timeline {
|
|||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is Timeline && runtimeType == other.runtimeType &&
|
||||
id == other.id;
|
||||
other is Timeline && runtimeType == other.runtimeType && id == other.id;
|
||||
|
||||
@override
|
||||
int get hashCode => id.hashCode;
|
||||
|
|
|
@ -26,6 +26,8 @@ class _EditorScreenState extends State<EditorScreen> {
|
|||
final spoilerController = TextEditingController();
|
||||
TimelineEntry? parentEntry;
|
||||
|
||||
var isSubmitting = false;
|
||||
|
||||
bool get isComment => widget.parentId.isNotEmpty;
|
||||
|
||||
String get statusType => widget.parentId.isEmpty ? 'Post' : 'Comment';
|
||||
|
@ -51,11 +53,17 @@ class _EditorScreenState extends State<EditorScreen> {
|
|||
buildSnackbar(context, "Can't submit an empty post/comment");
|
||||
return;
|
||||
}
|
||||
setState(() {
|
||||
isSubmitting = false;
|
||||
});
|
||||
final result = await manager.createNewStatus(
|
||||
contentController.text,
|
||||
spoilerText: spoilerController.text,
|
||||
inReplyToId: widget.parentId,
|
||||
);
|
||||
setState(() {
|
||||
isSubmitting = false;
|
||||
});
|
||||
|
||||
if (result.isFailure) {
|
||||
buildSnackbar(context, 'Error posting: ${result.error}');
|
||||
|
@ -85,6 +93,8 @@ class _EditorScreenState extends State<EditorScreen> {
|
|||
if (isComment && parentEntry != null)
|
||||
buildCommentPreview(context, parentEntry!),
|
||||
TextFormField(
|
||||
readOnly: isSubmitting,
|
||||
enabled: !isSubmitting,
|
||||
controller: spoilerController,
|
||||
decoration: InputDecoration(
|
||||
labelText: '$statusType Spoiler Text (optional)',
|
||||
|
@ -98,6 +108,8 @@ class _EditorScreenState extends State<EditorScreen> {
|
|||
),
|
||||
const VerticalPadding(),
|
||||
TextFormField(
|
||||
readOnly: isSubmitting,
|
||||
enabled: !isSubmitting,
|
||||
maxLines: 10,
|
||||
controller: contentController,
|
||||
decoration: InputDecoration(
|
||||
|
@ -116,14 +128,18 @@ class _EditorScreenState extends State<EditorScreen> {
|
|||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () async => createStatus(context, manager),
|
||||
onPressed: isSubmitting
|
||||
? null
|
||||
: () async => createStatus(context, manager),
|
||||
child: const Text('Submit'),
|
||||
),
|
||||
const HorizontalPadding(),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
context.pop();
|
||||
},
|
||||
onPressed: isSubmitting
|
||||
? null
|
||||
: () {
|
||||
context.pop();
|
||||
},
|
||||
child: const Text('Cancel'),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -24,6 +24,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||
var currentType = TimelineType.home;
|
||||
GroupData? currentGroup;
|
||||
final types = [
|
||||
TimelineType.self,
|
||||
TimelineType.home,
|
||||
TimelineType.global,
|
||||
TimelineType.local,
|
||||
|
@ -79,7 +80,10 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||
onPressed: () {
|
||||
context.push('/post/new');
|
||||
},
|
||||
icon: Icon(Icons.add),
|
||||
icon: Icon(
|
||||
Icons.add,
|
||||
color: Theme.of(context).primaryColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -13,11 +13,17 @@ class PostScreen extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
final manager = context.watch<TimelineManager>();
|
||||
final body = manager.getPostTreeEntryBy(id).fold(
|
||||
onSuccess: (post) => SingleChildScrollView(
|
||||
child: StatusControl(
|
||||
originalItem: post,
|
||||
openRemote: true,
|
||||
showStatusOpenButton: true,
|
||||
onSuccess: (post) => RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
await manager.refreshStatusChain(id);
|
||||
},
|
||||
child: SingleChildScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
child: StatusControl(
|
||||
originalItem: post,
|
||||
openRemote: true,
|
||||
showStatusOpenButton: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
onError: (error) => Text('Error getting post: $error'));
|
||||
|
|
Ładowanie…
Reference in New Issue