Move shared albums into our data dir

This commit is contained in:
Ming Ming 2021-08-08 20:09:21 +08:00
parent ac4a2aca15
commit a28f8b6c1b
5 changed files with 147 additions and 0 deletions

View file

@ -61,6 +61,11 @@ class Pref {
int getLanguageOr(int def) => getLanguage() ?? def;
Future<bool> setLanguage(int value) => _pref.setInt("language", value);
bool? hasNewSharedAlbum() => _pref.getBool("hasNewSharedAlbum");
bool hasNewSharedAlbumOr(bool def) => hasNewSharedAlbum() ?? def;
Future<bool> setNewSharedAlbum(bool value) =>
_pref.setBool("hasNewSharedAlbum", value);
Pref._();
static final _inst = Pref._();

View file

@ -4,6 +4,9 @@ import 'package:nc_photos/api/api_util.dart' as api_util;
String getRemoteAlbumsDir(Account account) =>
"${getRemoteStorageDir(account)}/albums";
String getRemotePendingSharedAlbumsDir(Account account) =>
"${getRemoteStorageDir(account)}/shared_albums";
String getRemoteTouchDir(Account account) =>
"${getRemoteStorageDir(account)}/touch";

View file

@ -0,0 +1,42 @@
import 'package:logging/logging.dart';
import 'package:nc_photos/account.dart';
import 'package:nc_photos/entity/album.dart';
import 'package:nc_photos/entity/file.dart';
import 'package:nc_photos/remote_storage_util.dart' as remote_storage_util;
import 'package:nc_photos/use_case/list_potential_shared_album.dart';
import 'package:nc_photos/use_case/move.dart';
import 'package:path/path.dart' as path;
/// Import new shared albums to the pending dir
class ImportPotentialSharedAlbum {
ImportPotentialSharedAlbum(this.fileRepo, this.albumRepo);
Future<List<Album>> call(Account account) async {
final products = <Album>[];
final files = await ListPotentialSharedAlbum(fileRepo)(account);
for (final f in files) {
// check if the file is actually an album
try {
final album = await albumRepo.get(account, f);
_log.info("[call] New shared album: ${album.name}, file: ${f.path}");
// move this file to the pending dir
await Move(fileRepo)(
account,
f,
"${remote_storage_util.getRemotePendingSharedAlbumsDir(account)}/${path.basename(f.path)}",
shouldCreateMissingDir: true,
);
products.add(album);
} catch (e, stacktrace) {
_log.severe("[call] Exception", e, stacktrace);
}
}
return products;
}
final FileRepo fileRepo;
final AlbumRepo albumRepo;
static final _log = Logger(
"user_case.import_potential_shared_album.ImportPotentialSharedAlbum");
}

View file

@ -0,0 +1,60 @@
import 'package:logging/logging.dart';
import 'package:nc_photos/account.dart';
import 'package:nc_photos/api/api_util.dart' as api_util;
import 'package:nc_photos/entity/file.dart';
import 'package:nc_photos/use_case/ls.dart';
import 'package:path/path.dart' as path;
/// List all shared files that are potentially albums
///
/// Beware that it's NOT guaranteed that they are actually albums
class ListPotentialSharedAlbum {
ListPotentialSharedAlbum(this.fileRepo);
Future<List<File>> call(Account account) async {
final results = <File>[];
final ls = await Ls(fileRepo)(
account, File(path: api_util.getWebdavRootUrlRelative(account)));
for (final f in ls) {
// check owner
if (_checkOwner(account, f) && _checkFileName(f)) {
results.add(f);
}
}
return results;
}
bool _checkOwner(Account account, File f) => !f.isOwned(account.username);
bool _checkFileName(File f) {
try {
final match = _regex.firstMatch(path.basename(f.path));
if (match == null) {
return false;
}
final timestamp = int.parse(match.group(1)!, radix: 16);
final time = DateTime.fromMillisecondsSinceEpoch(timestamp);
_log.fine("[_checkFileName] Timestamp: $time");
if (time.isAfter(DateTime.now())) {
_log.warning("[_checkFileName] Invalid timestamp: ${f.path}");
return false;
}
final random = int.parse(match.group(2)!, radix: 16);
_log.fine("[_checkFileName] Random: $random");
if (random > 0xFFFFFF) {
_log.warning("[_checkFileName] Invalid random: ${f.path}");
return false;
}
return true;
} catch (e, stacktrace) {
_log.warning("[_checkFileName] Exception: ${f.path}", e, stacktrace);
return false;
}
}
final FileRepo fileRepo;
final _regex = RegExp(r"^([0-9a-fA-F]+)-([0-9a-fA-F]+)\.nc_album\.json$");
static final _log =
Logger("user_case.list_potential_shared_album.ListPotentialSharedAlbum");
}

View file

@ -1,9 +1,16 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:logging/logging.dart';
import 'package:nc_photos/account.dart';
import 'package:nc_photos/app_localizations.dart';
import 'package:nc_photos/entity/album.dart';
import 'package:nc_photos/entity/file.dart';
import 'package:nc_photos/entity/file/data_source.dart';
import 'package:nc_photos/k.dart' as k;
import 'package:nc_photos/lab.dart';
import 'package:nc_photos/pref.dart';
import 'package:nc_photos/theme.dart';
import 'package:nc_photos/use_case/import_potential_shared_album.dart';
import 'package:nc_photos/widget/home_albums.dart';
import 'package:nc_photos/widget/home_photos.dart';
@ -37,6 +44,18 @@ class Home extends StatefulWidget {
}
class _HomeState extends State<Home> {
@override
initState() {
super.initState();
if (Lab().enableSharedAlbum) {
_importPotentialSharedAlbum().then((value) {
if (value.isNotEmpty) {
Pref.inst().setNewSharedAlbum(true);
}
});
}
}
@override
build(BuildContext context) {
return AppTheme(
@ -106,6 +125,24 @@ class _HomeState extends State<Home> {
});
}
Future<List<Album>> _importPotentialSharedAlbum() async {
final fileRepo = FileRepo(FileWebdavDataSource());
// don't want the potential albums to be cached at this moment
final albumRepo = AlbumRepo(AlbumRemoteDataSource());
try {
return await ImportPotentialSharedAlbum(fileRepo, albumRepo)(
widget.account);
} catch (e, stacktrace) {
_log.shout(
"[_importPotentialSharedAlbum] Failed while ImportPotentialSharedAlbum",
e,
stacktrace);
return [];
}
}
final _pageController = PageController(initialPage: 0, keepPage: false);
int _nextPage = 0;
static final _log = Logger("widget.home._HomeState");
}