kopia lustrzana https://gitlab.com/mysocialportal/relatica
Add new refresh status/request button to timeline page
rodzic
90574a83d7
commit
1c6a712c15
|
@ -20,40 +20,35 @@ class TimelinePanel extends StatelessWidget {
|
||||||
return Center(child: Text('Error getting timeline: ${result.error}'));
|
return Center(child: Text('Error getting timeline: ${result.error}'));
|
||||||
}
|
}
|
||||||
final items = result.value;
|
final items = result.value;
|
||||||
return RefreshIndicator(
|
return ListView.separated(
|
||||||
onRefresh: () async {
|
itemBuilder: (context, index) {
|
||||||
await manager.updateTimeline(timeline, TimelineRefreshType.refresh);
|
if (index == 0) {
|
||||||
},
|
return TextButton(
|
||||||
child: ListView.separated(
|
onPressed: () async => await manager.updateTimeline(
|
||||||
itemBuilder: (context, index) {
|
timeline, TimelineRefreshType.loadNewer),
|
||||||
if (index == 0) {
|
child: const Text('Load newer posts'));
|
||||||
return TextButton(
|
}
|
||||||
onPressed: () async => await manager.updateTimeline(
|
|
||||||
timeline, TimelineRefreshType.loadNewer),
|
|
||||||
child: const Text('Load newer posts'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index == items.length + 1) {
|
if (index == items.length + 1) {
|
||||||
return TextButton(
|
return TextButton(
|
||||||
onPressed: () async => await manager.updateTimeline(
|
onPressed: () async => await manager.updateTimeline(
|
||||||
timeline, TimelineRefreshType.loadOlder),
|
timeline, TimelineRefreshType.loadOlder),
|
||||||
child: const Text('Load older posts'));
|
child: const Text('Load older posts'));
|
||||||
}
|
}
|
||||||
final itemIndex = index - 1;
|
final itemIndex = index - 1;
|
||||||
final item = items[itemIndex];
|
final item = items[itemIndex];
|
||||||
_logger.finest(
|
_logger
|
||||||
'Building item: $itemIndex: ${item.entry.toShortString()}');
|
.finest('Building item: $itemIndex: ${item.entry.toShortString()}');
|
||||||
return PostControl(
|
return PostControl(
|
||||||
originalItem: item,
|
originalItem: item,
|
||||||
scrollToId: item.id,
|
scrollToId: item.id,
|
||||||
openRemote: false,
|
openRemote: false,
|
||||||
showStatusOpenButton: true,
|
showStatusOpenButton: true,
|
||||||
isRoot: false,
|
isRoot: false,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
separatorBuilder: (context, index) => Divider(),
|
separatorBuilder: (context, index) => Divider(),
|
||||||
itemCount: items.length + 2,
|
itemCount: items.length + 2,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,21 +243,25 @@ class FriendicaClient {
|
||||||
FutureResult<List<TimelineEntry>, ExecError> getUserTimeline(
|
FutureResult<List<TimelineEntry>, ExecError> getUserTimeline(
|
||||||
{String userId = '', int page = 1, int count = 10}) async {
|
{String userId = '', int page = 1, int count = 10}) async {
|
||||||
_logger.finest(() => 'Getting user timeline for $userId');
|
_logger.finest(() => 'Getting user timeline for $userId');
|
||||||
|
_networkStatusService.startTimelineLoading();
|
||||||
final baseUrl = 'https://$serverName/api/statuses/user_timeline?';
|
final baseUrl = 'https://$serverName/api/statuses/user_timeline?';
|
||||||
final pagingData = 'count=$count&page=$page';
|
final pagingData = 'count=$count&page=$page';
|
||||||
final url = userId.isEmpty
|
final url = userId.isEmpty
|
||||||
? '$baseUrl$pagingData'
|
? '$baseUrl$pagingData'
|
||||||
: '${baseUrl}screen_name=$userId$pagingData';
|
: '${baseUrl}screen_name=$userId$pagingData';
|
||||||
final request = Uri.parse(url);
|
final request = Uri.parse(url);
|
||||||
return (await _getApiListRequest(request).andThenSuccessAsync(
|
final result = (await _getApiListRequest(request).andThenSuccessAsync(
|
||||||
(postsJson) async => postsJson.data
|
(postsJson) async => postsJson.data
|
||||||
.map((json) => TimelineEntryMastodonExtensions.fromJson(json))
|
.map((json) => TimelineEntryMastodonExtensions.fromJson(json))
|
||||||
.toList()))
|
.toList()))
|
||||||
.mapError((error) => error as ExecError);
|
.execErrorCast();
|
||||||
|
_networkStatusService.finishTimelineLoading();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureResult<List<TimelineEntry>, ExecError> getTimeline(
|
FutureResult<List<TimelineEntry>, ExecError> getTimeline(
|
||||||
{required TimelineIdentifiers type, required PagingData page}) async {
|
{required TimelineIdentifiers type, required PagingData page}) async {
|
||||||
|
_networkStatusService.startTimelineLoading();
|
||||||
final String timelinePath = _typeToTimelinePath(type);
|
final String timelinePath = _typeToTimelinePath(type);
|
||||||
final String timelineQPs = _typeToTimelineQueryParameters(type);
|
final String timelineQPs = _typeToTimelineQueryParameters(type);
|
||||||
final baseUrl = 'https://$serverName/api/v1/$timelinePath';
|
final baseUrl = 'https://$serverName/api/v1/$timelinePath';
|
||||||
|
@ -265,11 +269,13 @@ class FriendicaClient {
|
||||||
'$baseUrl?exclude_replies=true&${page.toQueryParameters()}&$timelineQPs';
|
'$baseUrl?exclude_replies=true&${page.toQueryParameters()}&$timelineQPs';
|
||||||
final request = Uri.parse(url);
|
final request = Uri.parse(url);
|
||||||
_logger.finest(() => 'Getting ${type.toHumanKey()} with paging data $page');
|
_logger.finest(() => 'Getting ${type.toHumanKey()} with paging data $page');
|
||||||
return (await _getApiListRequest(request).andThenSuccessAsync(
|
final result = (await _getApiListRequest(request).andThenSuccessAsync(
|
||||||
(postsJson) async => postsJson.data
|
(postsJson) async => postsJson.data
|
||||||
.map((json) => TimelineEntryMastodonExtensions.fromJson(json))
|
.map((json) => TimelineEntryMastodonExtensions.fromJson(json))
|
||||||
.toList()))
|
.toList()))
|
||||||
.execErrorCast();
|
.execErrorCast();
|
||||||
|
_networkStatusService.finishTimelineLoading();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureResult<Uint8List, ExecError> getFileBytes(Uri url) async {
|
FutureResult<Uint8List, ExecError> getFileBytes(Uri url) async {
|
||||||
|
|
|
@ -6,8 +6,10 @@ import 'package:provider/provider.dart';
|
||||||
import '../controls/app_bottom_nav_bar.dart';
|
import '../controls/app_bottom_nav_bar.dart';
|
||||||
import '../controls/padding.dart';
|
import '../controls/padding.dart';
|
||||||
import '../controls/timeline/timeline_panel.dart';
|
import '../controls/timeline/timeline_panel.dart';
|
||||||
|
import '../globals.dart';
|
||||||
import '../models/TimelineIdentifiers.dart';
|
import '../models/TimelineIdentifiers.dart';
|
||||||
import '../models/group_data.dart';
|
import '../models/group_data.dart';
|
||||||
|
import '../services/network_status_service.dart';
|
||||||
import '../services/timeline_manager.dart';
|
import '../services/timeline_manager.dart';
|
||||||
|
|
||||||
class HomeScreen extends StatefulWidget {
|
class HomeScreen extends StatefulWidget {
|
||||||
|
@ -34,11 +36,13 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
_logger.finest('Build');
|
_logger.finest('Build');
|
||||||
final groups = context
|
final nss = getIt<NetworkStatusService>();
|
||||||
.watch<TimelineManager>()
|
final manager = context.watch<TimelineManager>();
|
||||||
.getGroups()
|
final groups = manager.getGroups().getValueOrElse(() => []).toList();
|
||||||
.getValueOrElse(() => [])
|
final currentTimeline = TimelineIdentifiers(
|
||||||
.toList();
|
timeline: currentType,
|
||||||
|
auxData: currentGroup?.id ?? '',
|
||||||
|
);
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
backgroundColor: Theme.of(context).canvasColor,
|
backgroundColor: Theme.of(context).canvasColor,
|
||||||
|
@ -76,6 +80,30 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
|
ValueListenableBuilder(
|
||||||
|
valueListenable: nss.timelineLoadingStatus,
|
||||||
|
builder: (context2, executing, _) {
|
||||||
|
if (executing) {
|
||||||
|
final theme = Theme.of(context);
|
||||||
|
final size = theme.appBarTheme.actionsIconTheme?.size ??
|
||||||
|
theme.iconTheme.size ??
|
||||||
|
24;
|
||||||
|
return Center(
|
||||||
|
child: SizedBox(
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return IconButton(
|
||||||
|
onPressed: () async => await manager.updateTimeline(
|
||||||
|
currentTimeline, TimelineRefreshType.refresh),
|
||||||
|
icon: Icon(
|
||||||
|
Icons.refresh,
|
||||||
|
color: Theme.of(context).textTheme.bodyText1!.color,
|
||||||
|
));
|
||||||
|
}),
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.push('/post/new');
|
context.push('/post/new');
|
||||||
|
@ -91,10 +119,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TimelinePanel(
|
child: TimelinePanel(
|
||||||
timeline: TimelineIdentifiers(
|
timeline: currentTimeline,
|
||||||
timeline: currentType,
|
|
||||||
auxData: currentGroup?.id ?? '',
|
|
||||||
),
|
|
||||||
)),
|
)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,18 +1,22 @@
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:logging/logging.dart';
|
|
||||||
|
|
||||||
class NetworkStatusService {
|
class NetworkStatusService {
|
||||||
static final _logger = Logger('$NetworkStatusService');
|
|
||||||
|
|
||||||
final notificationsUpdateStatus = ValueNotifier<bool>(false);
|
final notificationsUpdateStatus = ValueNotifier<bool>(false);
|
||||||
|
final timelineLoadingStatus = ValueNotifier<bool>(false);
|
||||||
|
|
||||||
void startNotificationUpdate() {
|
void startNotificationUpdate() {
|
||||||
_logger.info('Setting Notification Update status to true');
|
|
||||||
notificationsUpdateStatus.value = true;
|
notificationsUpdateStatus.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void finishNotificationUpdate() {
|
void finishNotificationUpdate() {
|
||||||
_logger.info('Setting Notification Update status to false');
|
|
||||||
notificationsUpdateStatus.value = false;
|
notificationsUpdateStatus.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void startTimelineLoading() {
|
||||||
|
timelineLoadingStatus.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void finishTimelineLoading() {
|
||||||
|
timelineLoadingStatus.value = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import Foundation
|
||||||
import desktop_window
|
import desktop_window
|
||||||
import flutter_secure_storage_macos
|
import flutter_secure_storage_macos
|
||||||
import objectbox_flutter_libs
|
import objectbox_flutter_libs
|
||||||
import path_provider_macos
|
import path_provider_foundation
|
||||||
import shared_preferences_foundation
|
import shared_preferences_foundation
|
||||||
import sqflite
|
import sqflite
|
||||||
import url_launcher_macos
|
import url_launcher_macos
|
||||||
|
|
Ładowanie…
Reference in New Issue