Compare commits
2 Commits
4b1942b949
...
76a03cc2fa
Author | SHA1 | Date | |
---|---|---|---|
76a03cc2fa | |||
3774760548 |
@ -106,6 +106,13 @@ files:
|
|||||||
extends: BackgroundEvent
|
extends: BackgroundEvent
|
||||||
implements:
|
implements:
|
||||||
- JsonImplementation
|
- JsonImplementation
|
||||||
|
# Triggered in response to a [GetBlocklistCommand]
|
||||||
|
- name: GetBlocklistResultEvent
|
||||||
|
extends: BackgroundEvent
|
||||||
|
implements:
|
||||||
|
- JsonImplementation
|
||||||
|
attributes:
|
||||||
|
entries: List<String>
|
||||||
# Triggered by DownloadService or UploadService.
|
# Triggered by DownloadService or UploadService.
|
||||||
- name: ProgressEvent
|
- name: ProgressEvent
|
||||||
extends: BackgroundEvent
|
extends: BackgroundEvent
|
||||||
@ -527,6 +534,11 @@ files:
|
|||||||
stickerPack:
|
stickerPack:
|
||||||
type: StickerPack
|
type: StickerPack
|
||||||
deserialise: true
|
deserialise: true
|
||||||
|
- name: GetBlocklistCommand
|
||||||
|
extends: BackgroundCommand
|
||||||
|
implements:
|
||||||
|
- JsonImplementation
|
||||||
|
attributes:
|
||||||
generate_builder: true
|
generate_builder: true
|
||||||
# get${builder_Name}FromJson
|
# get${builder_Name}FromJson
|
||||||
builder_name: "Command"
|
builder_name: "Command"
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
|
import 'dart:async';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
import 'package:moxxmpp/moxxmpp.dart';
|
import 'package:moxxmpp/moxxmpp.dart';
|
||||||
|
import 'package:moxxyv2/service/database/database.dart';
|
||||||
import 'package:moxxyv2/service/service.dart';
|
import 'package:moxxyv2/service/service.dart';
|
||||||
import 'package:moxxyv2/shared/events.dart';
|
import 'package:moxxyv2/shared/events.dart';
|
||||||
|
|
||||||
@ -9,35 +12,93 @@ enum BlockPushType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class BlocklistService {
|
class BlocklistService {
|
||||||
|
BlocklistService();
|
||||||
|
List<String>? _blocklist;
|
||||||
|
bool _requested = false;
|
||||||
|
bool? _supported;
|
||||||
|
final Logger _log = Logger('BlocklistService');
|
||||||
|
|
||||||
BlocklistService() :
|
void onNewConnection() {
|
||||||
_blocklistCache = List.empty(growable: true),
|
// Invalidate the caches
|
||||||
_requestedBlocklist = false;
|
_blocklist = null;
|
||||||
final List<String> _blocklistCache;
|
_requested = false;
|
||||||
bool _requestedBlocklist;
|
_supported = null;
|
||||||
|
}
|
||||||
|
|
||||||
Future<List<String>> _requestBlocklist() async {
|
Future<bool> _checkSupport() async {
|
||||||
final manager = GetIt.I.get<XmppConnection>().getManagerById<BlockingManager>(blockingManager)!;
|
return _supported ??= await GetIt.I.get<XmppConnection>()
|
||||||
_blocklistCache
|
.getManagerById<BlockingManager>(blockingManager)!
|
||||||
..clear()
|
.isSupported();
|
||||||
..addAll(await manager.getBlocklist());
|
}
|
||||||
_requestedBlocklist = true;
|
|
||||||
return _blocklistCache;
|
Future<void> _requestBlocklist() async {
|
||||||
|
assert(_blocklist != null, 'The blocklist must be loaded from the database before requesting');
|
||||||
|
|
||||||
|
// Check if blocking is supported
|
||||||
|
if (!(await _checkSupport())) {
|
||||||
|
_log.warning('Blocklist requested but server does not support it.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final blocklist = await GetIt.I.get<XmppConnection>()
|
||||||
|
.getManagerById<BlockingManager>(blockingManager)!
|
||||||
|
.getBlocklist();
|
||||||
|
|
||||||
|
// Diff the received blocklist with the cache
|
||||||
|
final newItems = List<String>.empty(growable: true);
|
||||||
|
final removedItems = List<String>.empty(growable: true);
|
||||||
|
final db = GetIt.I.get<DatabaseService>();
|
||||||
|
for (final item in blocklist) {
|
||||||
|
if (!_blocklist!.contains(item)) {
|
||||||
|
await db.addBlocklistEntry(item);
|
||||||
|
_blocklist!.add(item);
|
||||||
|
newItems.add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Diff the cache with the received blocklist
|
||||||
|
for (final item in _blocklist!) {
|
||||||
|
if (!blocklist.contains(item)) {
|
||||||
|
await db.removeBlocklistEntry(item);
|
||||||
|
_blocklist!.remove(item);
|
||||||
|
removedItems.add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_requested = true;
|
||||||
|
|
||||||
|
// Trigger an UI event if we have anything to tell the UI
|
||||||
|
if (newItems.isNotEmpty || removedItems.isNotEmpty) {
|
||||||
|
sendEvent(
|
||||||
|
BlocklistPushEvent(
|
||||||
|
added: newItems,
|
||||||
|
removed: removedItems,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the blocklist from the database
|
/// Returns the blocklist from the database
|
||||||
Future<List<String>> getBlocklist() async {
|
Future<List<String>> getBlocklist() async {
|
||||||
if (!_requestedBlocklist) {
|
if (_blocklist == null) {
|
||||||
_blocklistCache
|
_blocklist = await GetIt.I.get<DatabaseService>().getBlocklistEntries();
|
||||||
..clear()
|
|
||||||
..addAll(await _requestBlocklist());
|
if (!_requested) {
|
||||||
|
unawaited(_requestBlocklist());
|
||||||
|
}
|
||||||
|
|
||||||
|
return _blocklist!;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _blocklistCache;
|
if (!_requested) {
|
||||||
|
unawaited(_requestBlocklist());
|
||||||
|
}
|
||||||
|
|
||||||
|
return _blocklist!;
|
||||||
}
|
}
|
||||||
|
|
||||||
void onUnblockAllPush() {
|
void onUnblockAllPush() {
|
||||||
_blocklistCache.clear();
|
_blocklist = List<String>.empty(growable: true);
|
||||||
sendEvent(
|
sendEvent(
|
||||||
BlocklistUnblockAllEvent(),
|
BlocklistUnblockAllEvent(),
|
||||||
);
|
);
|
||||||
@ -45,21 +106,25 @@ class BlocklistService {
|
|||||||
|
|
||||||
Future<void> onBlocklistPush(BlockPushType type, List<String> items) async {
|
Future<void> onBlocklistPush(BlockPushType type, List<String> items) async {
|
||||||
// We will fetch it later when getBlocklist is called
|
// We will fetch it later when getBlocklist is called
|
||||||
if (!_requestedBlocklist) return;
|
if (!_requested) return;
|
||||||
|
|
||||||
final newBlocks = List<String>.empty(growable: true);
|
final newBlocks = List<String>.empty(growable: true);
|
||||||
final removedBlocks = List<String>.empty(growable: true);
|
final removedBlocks = List<String>.empty(growable: true);
|
||||||
for (final item in items) {
|
for (final item in items) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case BlockPushType.block: {
|
case BlockPushType.block: {
|
||||||
if (_blocklistCache.contains(item)) continue;
|
if (_blocklist!.contains(item)) continue;
|
||||||
_blocklistCache.add(item);
|
_blocklist!.add(item);
|
||||||
newBlocks.add(item);
|
newBlocks.add(item);
|
||||||
|
|
||||||
|
await GetIt.I.get<DatabaseService>().addBlocklistEntry(item);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BlockPushType.unblock: {
|
case BlockPushType.unblock: {
|
||||||
_blocklistCache.removeWhere((i) => i == item);
|
_blocklist!.removeWhere((i) => i == item);
|
||||||
removedBlocks.add(item);
|
removedBlocks.add(item);
|
||||||
|
|
||||||
|
await GetIt.I.get<DatabaseService>().removeBlocklistEntry(item);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -74,17 +139,47 @@ class BlocklistService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> blockJid(String jid) async {
|
Future<bool> blockJid(String jid) async {
|
||||||
final manager = GetIt.I.get<XmppConnection>().getManagerById<BlockingManager>(blockingManager)!;
|
// Check if blocking is supported
|
||||||
return manager.block([ jid ]);
|
if (!(await _checkSupport())) {
|
||||||
|
_log.warning('Blocking $jid requested but server does not support it.');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_blocklist!.add(jid);
|
||||||
|
await GetIt.I.get<DatabaseService>()
|
||||||
|
.addBlocklistEntry(jid);
|
||||||
|
return GetIt.I.get<XmppConnection>()
|
||||||
|
.getManagerById<BlockingManager>(blockingManager)!
|
||||||
|
.block([jid]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> unblockJid(String jid) async {
|
Future<bool> unblockJid(String jid) async {
|
||||||
final manager = GetIt.I.get<XmppConnection>().getManagerById<BlockingManager>(blockingManager)!;
|
// Check if blocking is supported
|
||||||
return manager.unblock([ jid ]);
|
if (!(await _checkSupport())) {
|
||||||
|
_log.warning('Unblocking $jid requested but server does not support it.');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_blocklist!.remove(jid);
|
||||||
|
await GetIt.I.get<DatabaseService>()
|
||||||
|
.removeBlocklistEntry(jid);
|
||||||
|
return GetIt.I.get<XmppConnection>()
|
||||||
|
.getManagerById<BlockingManager>(blockingManager)!
|
||||||
|
.unblock([jid]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> unblockAll() async {
|
Future<bool> unblockAll() async {
|
||||||
final manager = GetIt.I.get<XmppConnection>().getManagerById<BlockingManager>(blockingManager)!;
|
// Check if blocking is supported
|
||||||
return manager.unblockAll();
|
if (!(await _checkSupport())) {
|
||||||
|
_log.warning('Unblocking all JIDs requested but server does not support it.');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_blocklist!.clear();
|
||||||
|
await GetIt.I.get<DatabaseService>()
|
||||||
|
.removeAllBlocklistEntries();
|
||||||
|
return GetIt.I.get<XmppConnection>()
|
||||||
|
.getManagerById<BlockingManager>(blockingManager)!
|
||||||
|
.unblockAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ const xmppStateTable = 'XmppState';
|
|||||||
const contactsTable = 'Contacts';
|
const contactsTable = 'Contacts';
|
||||||
const stickersTable = 'Stickers';
|
const stickersTable = 'Stickers';
|
||||||
const stickerPacksTable = 'StickerPacks';
|
const stickerPacksTable = 'StickerPacks';
|
||||||
|
const blocklistTable = 'Blocklist';
|
||||||
|
|
||||||
const typeString = 0;
|
const typeString = 0;
|
||||||
const typeInt = 1;
|
const typeInt = 1;
|
||||||
|
@ -159,6 +159,15 @@ Future<void> createDatabase(Database db, int version) async {
|
|||||||
)''',
|
)''',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Blocklist
|
||||||
|
await db.execute(
|
||||||
|
'''
|
||||||
|
CREATE TABLE $blocklistTable (
|
||||||
|
jid TEXT PRIMARY KEY
|
||||||
|
);
|
||||||
|
''',
|
||||||
|
);
|
||||||
|
|
||||||
// OMEMO
|
// OMEMO
|
||||||
await db.execute(
|
await db.execute(
|
||||||
'''
|
'''
|
||||||
|
@ -8,6 +8,7 @@ import 'package:moxxmpp/moxxmpp.dart';
|
|||||||
import 'package:moxxyv2/service/database/constants.dart';
|
import 'package:moxxyv2/service/database/constants.dart';
|
||||||
import 'package:moxxyv2/service/database/creation.dart';
|
import 'package:moxxyv2/service/database/creation.dart';
|
||||||
import 'package:moxxyv2/service/database/helpers.dart';
|
import 'package:moxxyv2/service/database/helpers.dart';
|
||||||
|
import 'package:moxxyv2/service/database/migrations/0000_blocklist.dart';
|
||||||
import 'package:moxxyv2/service/database/migrations/0000_contacts_integration.dart';
|
import 'package:moxxyv2/service/database/migrations/0000_contacts_integration.dart';
|
||||||
import 'package:moxxyv2/service/database/migrations/0000_contacts_integration_avatar.dart';
|
import 'package:moxxyv2/service/database/migrations/0000_contacts_integration_avatar.dart';
|
||||||
import 'package:moxxyv2/service/database/migrations/0000_contacts_integration_pseudo.dart';
|
import 'package:moxxyv2/service/database/migrations/0000_contacts_integration_pseudo.dart';
|
||||||
@ -79,7 +80,7 @@ class DatabaseService {
|
|||||||
_db = await openDatabase(
|
_db = await openDatabase(
|
||||||
dbPath,
|
dbPath,
|
||||||
password: key,
|
password: key,
|
||||||
version: 22,
|
version: 23,
|
||||||
onCreate: createDatabase,
|
onCreate: createDatabase,
|
||||||
onConfigure: (db) async {
|
onConfigure: (db) async {
|
||||||
// In order to do schema changes during database upgrades, we disable foreign
|
// In order to do schema changes during database upgrades, we disable foreign
|
||||||
@ -176,6 +177,10 @@ class DatabaseService {
|
|||||||
_log.finest('Running migration for database version 22');
|
_log.finest('Running migration for database version 22');
|
||||||
await upgradeFromV21ToV22(db);
|
await upgradeFromV21ToV22(db);
|
||||||
}
|
}
|
||||||
|
if (oldVersion < 23) {
|
||||||
|
_log.finest('Running migration for database version 23');
|
||||||
|
await upgradeFromV22ToV23(db);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1257,4 +1262,35 @@ class DatabaseService {
|
|||||||
.toList(),
|
.toList(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> addBlocklistEntry(String jid) async {
|
||||||
|
await _db.insert(
|
||||||
|
blocklistTable,
|
||||||
|
{
|
||||||
|
'jid': jid,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> removeBlocklistEntry(String jid) async {
|
||||||
|
await _db.delete(
|
||||||
|
blocklistTable,
|
||||||
|
where: 'jid = ?',
|
||||||
|
whereArgs: [jid],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> removeAllBlocklistEntries() async {
|
||||||
|
await _db.delete(
|
||||||
|
blocklistTable,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<String>> getBlocklistEntries() async {
|
||||||
|
final result = await _db.query(blocklistTable);
|
||||||
|
|
||||||
|
return result
|
||||||
|
.map((m) => m['jid']! as String)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
13
lib/service/database/migrations/0000_blocklist.dart
Normal file
13
lib/service/database/migrations/0000_blocklist.dart
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import 'package:moxxyv2/service/database/constants.dart';
|
||||||
|
import 'package:moxxyv2/shared/models/preference.dart';
|
||||||
|
import 'package:sqflite_sqlcipher/sqflite.dart';
|
||||||
|
|
||||||
|
Future<void> upgradeFromV22ToV23(Database db) async {
|
||||||
|
await db.execute(
|
||||||
|
'''
|
||||||
|
CREATE TABLE $blocklistTable (
|
||||||
|
jid TEXT PRIMARY KEY
|
||||||
|
);
|
||||||
|
''',
|
||||||
|
);
|
||||||
|
}
|
@ -79,6 +79,7 @@ void setupBackgroundEventHandler() {
|
|||||||
EventTypeMatcher<RemoveStickerPackCommand>(performRemoveStickerPack),
|
EventTypeMatcher<RemoveStickerPackCommand>(performRemoveStickerPack),
|
||||||
EventTypeMatcher<FetchStickerPackCommand>(performFetchStickerPack),
|
EventTypeMatcher<FetchStickerPackCommand>(performFetchStickerPack),
|
||||||
EventTypeMatcher<InstallStickerPackCommand>(performStickerPackInstall),
|
EventTypeMatcher<InstallStickerPackCommand>(performStickerPackInstall),
|
||||||
|
EventTypeMatcher<GetBlocklistCommand>(performGetBlocklist),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
GetIt.I.registerSingleton<EventHandler>(handler);
|
GetIt.I.registerSingleton<EventHandler>(handler);
|
||||||
@ -890,3 +891,15 @@ Future<void> performStickerPackInstall(InstallStickerPackCommand command, { dyna
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> performGetBlocklist(GetBlocklistCommand command, { dynamic extra }) async {
|
||||||
|
final id = extra as String;
|
||||||
|
|
||||||
|
final result = await GetIt.I.get<BlocklistService>().getBlocklist();
|
||||||
|
sendEvent(
|
||||||
|
GetBlocklistResultEvent(
|
||||||
|
entries: result,
|
||||||
|
),
|
||||||
|
id: id,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -361,7 +361,7 @@ class HttpFileTransferService {
|
|||||||
// Prepare file and completer.
|
// Prepare file and completer.
|
||||||
final file = await File(downloadedPath).create();
|
final file = await File(downloadedPath).create();
|
||||||
final fileSink = file.openWrite(mode: FileMode.writeOnlyAppend);
|
final fileSink = file.openWrite(mode: FileMode.writeOnlyAppend);
|
||||||
final downloadCompleter = Completer();
|
final downloadCompleter = Completer<void>();
|
||||||
|
|
||||||
dio.Response<dio.ResponseBody>? response;
|
dio.Response<dio.ResponseBody>? response;
|
||||||
|
|
||||||
|
@ -665,6 +665,9 @@ class XmppService {
|
|||||||
unawaited(_initializeOmemoService(settings.jid.toString()));
|
unawaited(_initializeOmemoService(settings.jid.toString()));
|
||||||
|
|
||||||
if (!event.resumed) {
|
if (!event.resumed) {
|
||||||
|
// Reset the blocking service's cache
|
||||||
|
GetIt.I.get<BlocklistService>().onNewConnection();
|
||||||
|
|
||||||
// Enable carbons
|
// Enable carbons
|
||||||
final carbonsResult = await connection
|
final carbonsResult = await connection
|
||||||
.getManagerById<CarbonsManager>(carbonsManager)!
|
.getManagerById<CarbonsManager>(carbonsManager)!
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:moxplatform/moxplatform.dart';
|
import 'package:moxplatform/moxplatform.dart';
|
||||||
import 'package:moxxyv2/shared/commands.dart';
|
import 'package:moxxyv2/shared/commands.dart';
|
||||||
|
import 'package:moxxyv2/shared/events.dart';
|
||||||
|
import 'package:moxxyv2/ui/bloc/navigation_bloc.dart';
|
||||||
|
import 'package:moxxyv2/ui/constants.dart';
|
||||||
|
|
||||||
part 'blocklist_bloc.freezed.dart';
|
part 'blocklist_bloc.freezed.dart';
|
||||||
part 'blocklist_event.dart';
|
part 'blocklist_event.dart';
|
||||||
@ -9,11 +13,44 @@ part 'blocklist_state.dart';
|
|||||||
|
|
||||||
class BlocklistBloc extends Bloc<BlocklistEvent, BlocklistState> {
|
class BlocklistBloc extends Bloc<BlocklistEvent, BlocklistState> {
|
||||||
BlocklistBloc() : super(BlocklistState()) {
|
BlocklistBloc() : super(BlocklistState()) {
|
||||||
|
on<BlocklistRequestedEvent>(_onBlocklistRequested);
|
||||||
on<UnblockedJidEvent>(_onJidUnblocked);
|
on<UnblockedJidEvent>(_onJidUnblocked);
|
||||||
on<UnblockedAllEvent>(_onUnblockedAll);
|
on<UnblockedAllEvent>(_onUnblockedAll);
|
||||||
on<BlocklistPushedEvent>(_onBlocklistPushed);
|
on<BlocklistPushedEvent>(_onBlocklistPushed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _onBlocklistRequested(BlocklistRequestedEvent event, Emitter<BlocklistState> emit) async {
|
||||||
|
final mustDoWork = state.blocklist.isEmpty;
|
||||||
|
|
||||||
|
if (mustDoWork) {
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
isWorking: true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
GetIt.I.get<NavigationBloc>().add(
|
||||||
|
PushedNamedEvent(
|
||||||
|
const NavigationDestination(blocklistRoute),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (state.blocklist.isEmpty) {
|
||||||
|
// ignore: cast_nullable_to_non_nullable
|
||||||
|
final result = await MoxplatformPlugin.handler.getDataSender().sendData(
|
||||||
|
GetBlocklistCommand(),
|
||||||
|
) as GetBlocklistResultEvent;
|
||||||
|
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
blocklist: result.entries,
|
||||||
|
isWorking: false,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _onJidUnblocked(UnblockedJidEvent event, Emitter<BlocklistState> emit) async {
|
Future<void> _onJidUnblocked(UnblockedJidEvent event, Emitter<BlocklistState> emit) async {
|
||||||
await MoxplatformPlugin.handler.getDataSender().sendData(
|
await MoxplatformPlugin.handler.getDataSender().sendData(
|
||||||
UnblockJidCommand(
|
UnblockJidCommand(
|
||||||
|
@ -2,9 +2,11 @@ part of 'blocklist_bloc.dart';
|
|||||||
|
|
||||||
abstract class BlocklistEvent {}
|
abstract class BlocklistEvent {}
|
||||||
|
|
||||||
|
/// Triggered when the blocklist page has been requested
|
||||||
|
class BlocklistRequestedEvent extends BlocklistEvent {}
|
||||||
|
|
||||||
/// Triggered when a JID is unblocked
|
/// Triggered when a JID is unblocked
|
||||||
class UnblockedJidEvent extends BlocklistEvent {
|
class UnblockedJidEvent extends BlocklistEvent {
|
||||||
|
|
||||||
UnblockedJidEvent(this.jid);
|
UnblockedJidEvent(this.jid);
|
||||||
final String jid;
|
final String jid;
|
||||||
}
|
}
|
||||||
@ -16,7 +18,6 @@ class UnblockedAllEvent extends BlocklistEvent {
|
|||||||
|
|
||||||
/// Triggered when we receive a blocklist push
|
/// Triggered when we receive a blocklist push
|
||||||
class BlocklistPushedEvent extends BlocklistEvent {
|
class BlocklistPushedEvent extends BlocklistEvent {
|
||||||
|
|
||||||
BlocklistPushedEvent(this.added, this.removed);
|
BlocklistPushedEvent(this.added, this.removed);
|
||||||
final List<String> added;
|
final List<String> added;
|
||||||
final List<String> removed;
|
final List<String> removed;
|
||||||
|
@ -4,5 +4,6 @@ part of 'blocklist_bloc.dart';
|
|||||||
class BlocklistState with _$BlocklistState {
|
class BlocklistState with _$BlocklistState {
|
||||||
factory BlocklistState({
|
factory BlocklistState({
|
||||||
@Default(<String>[]) List<String> blocklist,
|
@Default(<String>[]) List<String> blocklist,
|
||||||
|
@Default(false) bool isWorking,
|
||||||
}) = _BlocklistState;
|
}) = _BlocklistState;
|
||||||
}
|
}
|
||||||
|
@ -23,59 +23,74 @@ class BlocklistPage extends StatelessWidget {
|
|||||||
Widget _buildListView(BlocklistState state) {
|
Widget _buildListView(BlocklistState state) {
|
||||||
// ignore: non_bool_condition,avoid_dynamic_calls
|
// ignore: non_bool_condition,avoid_dynamic_calls
|
||||||
if (state.blocklist.isEmpty) {
|
if (state.blocklist.isEmpty) {
|
||||||
return Padding(
|
return Column(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: paddingVeryLarge),
|
children: [
|
||||||
child: Column(
|
if (state.isWorking)
|
||||||
children: [
|
const LinearProgressIndicator(),
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 8),
|
Padding(
|
||||||
child: Image.asset('assets/images/happy_news.png'),
|
padding: const EdgeInsets.symmetric(horizontal: paddingVeryLarge),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8),
|
||||||
|
child: Image.asset('assets/images/happy_news.png'),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8),
|
||||||
|
child: Text(t.pages.blocklist.noUsersBlocked),
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
Padding(
|
),
|
||||||
padding: const EdgeInsets.only(top: 8),
|
],
|
||||||
child: Text(t.pages.blocklist.noUsersBlocked),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ListView.builder(
|
return Column(
|
||||||
itemCount: state.blocklist.length,
|
children: [
|
||||||
itemBuilder: (BuildContext context, int index) {
|
if (state.isWorking)
|
||||||
// ignore: avoid_dynamic_calls
|
const LinearProgressIndicator(),
|
||||||
final jid = state.blocklist[index];
|
|
||||||
|
|
||||||
return Padding(
|
ListView.builder(
|
||||||
padding: const EdgeInsets.symmetric(
|
shrinkWrap: true,
|
||||||
horizontal: 32,
|
itemCount: state.blocklist.length,
|
||||||
vertical: 16,
|
itemBuilder: (BuildContext context, int index) {
|
||||||
),
|
// ignore: avoid_dynamic_calls
|
||||||
child: Row(
|
final jid = state.blocklist[index];
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: Text(jid),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.delete),
|
|
||||||
color: Colors.red,
|
|
||||||
onPressed: () async {
|
|
||||||
final result = await showConfirmationDialog(
|
|
||||||
t.pages.blocklist.unblockJidConfirmTitle(jid: jid),
|
|
||||||
t.pages.blocklist.unblockJidConfirmBody(jid: jid),
|
|
||||||
context,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (result) {
|
return Padding(
|
||||||
// ignore: use_build_context_synchronously
|
padding: const EdgeInsets.symmetric(
|
||||||
context.read<BlocklistBloc>().add(UnblockedJidEvent(jid));
|
horizontal: 32,
|
||||||
}
|
vertical: 16,
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
child: Row(
|
||||||
),
|
children: [
|
||||||
);
|
Expanded(
|
||||||
},
|
child: Text(jid),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.delete),
|
||||||
|
color: Colors.red,
|
||||||
|
onPressed: () async {
|
||||||
|
final result = await showConfirmationDialog(
|
||||||
|
t.pages.blocklist.unblockJidConfirmTitle(jid: jid),
|
||||||
|
t.pages.blocklist.unblockJidConfirmBody(jid: jid),
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
// ignore: use_build_context_synchronously
|
||||||
|
context.read<BlocklistBloc>().add(UnblockedJidEvent(jid));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,6 +123,7 @@ class BlocklistPage extends StatelessWidget {
|
|||||||
icon: const Icon(Icons.more_vert),
|
icon: const Icon(Icons.more_vert),
|
||||||
itemBuilder: (BuildContext context) => [
|
itemBuilder: (BuildContext context) => [
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
|
enabled: state.blocklist.isNotEmpty,
|
||||||
value: BlocklistOptions.unblockAll,
|
value: BlocklistOptions.unblockAll,
|
||||||
child: Text(t.pages.blocklist.unblockAll),
|
child: Text(t.pages.blocklist.unblockAll),
|
||||||
),
|
),
|
||||||
|
@ -2,6 +2,7 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:moxxyv2/i18n/strings.g.dart';
|
import 'package:moxxyv2/i18n/strings.g.dart';
|
||||||
|
import 'package:moxxyv2/ui/bloc/blocklist_bloc.dart';
|
||||||
import 'package:moxxyv2/ui/bloc/preferences_bloc.dart';
|
import 'package:moxxyv2/ui/bloc/preferences_bloc.dart';
|
||||||
import 'package:moxxyv2/ui/constants.dart';
|
import 'package:moxxyv2/ui/constants.dart';
|
||||||
import 'package:moxxyv2/ui/helpers.dart';
|
import 'package:moxxyv2/ui/helpers.dart';
|
||||||
@ -76,7 +77,9 @@ class SettingsPage extends StatelessWidget {
|
|||||||
child: Icon(Icons.block),
|
child: Icon(Icons.block),
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.pushNamed(context, blocklistRoute);
|
GetIt.I.get<BlocklistBloc>().add(
|
||||||
|
BlocklistRequestedEvent(),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
SettingsRow(
|
SettingsRow(
|
||||||
|
Loading…
Reference in New Issue
Block a user