[client] Send and store content type information

This commit is contained in:
Abhishek Shroff
2024-09-12 00:16:41 +05:30
parent 4dd49d9759
commit 0d8815aed7
8 changed files with 91 additions and 19 deletions

View File

@@ -51,7 +51,7 @@ class ResourceMkdirAction extends ApiAction<PhylumAccount> with JsonApiAction {
@override
FutureOr<void> applyOptimisticUpdate(PhylumAccount account) {
account.resourceRepository.createResource(id, true, parent, resourceName);
account.resourceRepository.createResource(id, true, parent, resourceName, '');
}
@override

View File

@@ -2,6 +2,8 @@ import 'dart:async';
import 'dart:io';
import 'package:http/http.dart';
import 'package:http_parser/http_parser.dart';
import 'package:mime/mime.dart';
import 'package:offtheline/offtheline.dart';
import 'package:phylum/libphylum/phylum_account.dart';
import 'package:phylum/libphylum/phylum_datastore.dart';
@@ -22,21 +24,17 @@ class ResourceUploadAction extends ApiAction<PhylumAccount> with FileUploadApiAc
get tag => resourceSummaryResponse;
@override
Future<MultipartFile> get file => MultipartFile.fromPath('contents', path, filename: resourceName);
Future<MultipartFile> get file => MultipartFile.fromPath('contents', path, filename: resourceName, contentType: MediaType.parse(contentType));
final String id;
final String parent;
final String resourceName;
final String path;
final int size;
final String contentType;
ResourceUploadAction._({
required this.id,
required this.parent,
required this.resourceName,
required this.path,
required this.size,
});
ResourceUploadAction._(
{required this.id, required this.parent, required this.resourceName, required this.path, required this.size, required this.contentType});
static Future<ResourceUploadAction> fromPath({
required String parent,
@@ -51,6 +49,7 @@ class ResourceUploadAction extends ApiAction<PhylumAccount> with FileUploadApiAc
resourceName: resourceName,
path: path,
size: size,
contentType: lookupMimeType(path) ?? 'application/octet-stream',
);
}
@@ -61,6 +60,7 @@ class ResourceUploadAction extends ApiAction<PhylumAccount> with FileUploadApiAc
resourceName: map['resourceName'],
path: map['path'],
size: map['size'],
contentType: map['contentType'],
);
}
@@ -71,7 +71,7 @@ class ResourceUploadAction extends ApiAction<PhylumAccount> with FileUploadApiAc
@override
FutureOr<void> applyOptimisticUpdate(PhylumAccount account) {
account.resourceRepository.createResource(id, true, parent, resourceName);
account.resourceRepository.createResource(id, true, parent, resourceName, contentType);
}
@override
@@ -86,6 +86,7 @@ class ResourceUploadAction extends ApiAction<PhylumAccount> with FileUploadApiAc
'resourceName': resourceName,
'path': path,
'size': size,
'contentType': contentType,
};
@override

View File

@@ -51,6 +51,12 @@ class $ResourcesTable extends Resources
late final GeneratedColumn<String> etag = GeneratedColumn<String>(
'etag', aliasedName, false,
type: DriftSqlType.string, requiredDuringInsert: true);
static const VerificationMeta _contentTypeMeta =
const VerificationMeta('contentType');
@override
late final GeneratedColumn<String> contentType = GeneratedColumn<String>(
'content_type', aliasedName, false,
type: DriftSqlType.string, requiredDuringInsert: true);
static const VerificationMeta _deletedMeta =
const VerificationMeta('deleted');
@override
@@ -68,8 +74,18 @@ class $ResourcesTable extends Resources
'last_fetch', aliasedName, true,
type: DriftSqlType.dateTime, requiredDuringInsert: false);
@override
List<GeneratedColumn> get $columns =>
[id, parent, name, dir, modified, size, etag, deleted, lastFetch];
List<GeneratedColumn> get $columns => [
id,
parent,
name,
dir,
modified,
size,
etag,
contentType,
deleted,
lastFetch
];
@override
String get aliasedName => _alias ?? actualTableName;
@override
@@ -119,6 +135,14 @@ class $ResourcesTable extends Resources
} else if (isInserting) {
context.missing(_etagMeta);
}
if (data.containsKey('content_type')) {
context.handle(
_contentTypeMeta,
contentType.isAcceptableOrUnknown(
data['content_type']!, _contentTypeMeta));
} else if (isInserting) {
context.missing(_contentTypeMeta);
}
if (data.containsKey('deleted')) {
context.handle(_deletedMeta,
deleted.isAcceptableOrUnknown(data['deleted']!, _deletedMeta));
@@ -154,6 +178,8 @@ class $ResourcesTable extends Resources
.read(DriftSqlType.int, data['${effectivePrefix}size'])!,
etag: attachedDatabase.typeMapping
.read(DriftSqlType.string, data['${effectivePrefix}etag'])!,
contentType: attachedDatabase.typeMapping
.read(DriftSqlType.string, data['${effectivePrefix}content_type'])!,
deleted: attachedDatabase.typeMapping
.read(DriftSqlType.bool, data['${effectivePrefix}deleted'])!,
lastFetch: attachedDatabase.typeMapping
@@ -175,6 +201,7 @@ class Resource extends DataClass implements Insertable<Resource> {
final DateTime modified;
final int size;
final String etag;
final String contentType;
final bool deleted;
final DateTime? lastFetch;
const Resource(
@@ -185,6 +212,7 @@ class Resource extends DataClass implements Insertable<Resource> {
required this.modified,
required this.size,
required this.etag,
required this.contentType,
required this.deleted,
this.lastFetch});
@override
@@ -199,6 +227,7 @@ class Resource extends DataClass implements Insertable<Resource> {
map['modified'] = Variable<DateTime>(modified);
map['size'] = Variable<int>(size);
map['etag'] = Variable<String>(etag);
map['content_type'] = Variable<String>(contentType);
map['deleted'] = Variable<bool>(deleted);
if (!nullToAbsent || lastFetch != null) {
map['last_fetch'] = Variable<DateTime>(lastFetch);
@@ -216,6 +245,7 @@ class Resource extends DataClass implements Insertable<Resource> {
modified: Value(modified),
size: Value(size),
etag: Value(etag),
contentType: Value(contentType),
deleted: Value(deleted),
lastFetch: lastFetch == null && nullToAbsent
? const Value.absent()
@@ -234,6 +264,7 @@ class Resource extends DataClass implements Insertable<Resource> {
modified: serializer.fromJson<DateTime>(json['modified']),
size: serializer.fromJson<int>(json['size']),
etag: serializer.fromJson<String>(json['etag']),
contentType: serializer.fromJson<String>(json['contentType']),
deleted: serializer.fromJson<bool>(json['deleted']),
lastFetch: serializer.fromJson<DateTime?>(json['lastFetch']),
);
@@ -249,6 +280,7 @@ class Resource extends DataClass implements Insertable<Resource> {
'modified': serializer.toJson<DateTime>(modified),
'size': serializer.toJson<int>(size),
'etag': serializer.toJson<String>(etag),
'contentType': serializer.toJson<String>(contentType),
'deleted': serializer.toJson<bool>(deleted),
'lastFetch': serializer.toJson<DateTime?>(lastFetch),
};
@@ -262,6 +294,7 @@ class Resource extends DataClass implements Insertable<Resource> {
DateTime? modified,
int? size,
String? etag,
String? contentType,
bool? deleted,
Value<DateTime?> lastFetch = const Value.absent()}) =>
Resource(
@@ -272,6 +305,7 @@ class Resource extends DataClass implements Insertable<Resource> {
modified: modified ?? this.modified,
size: size ?? this.size,
etag: etag ?? this.etag,
contentType: contentType ?? this.contentType,
deleted: deleted ?? this.deleted,
lastFetch: lastFetch.present ? lastFetch.value : this.lastFetch,
);
@@ -284,6 +318,8 @@ class Resource extends DataClass implements Insertable<Resource> {
modified: data.modified.present ? data.modified.value : this.modified,
size: data.size.present ? data.size.value : this.size,
etag: data.etag.present ? data.etag.value : this.etag,
contentType:
data.contentType.present ? data.contentType.value : this.contentType,
deleted: data.deleted.present ? data.deleted.value : this.deleted,
lastFetch: data.lastFetch.present ? data.lastFetch.value : this.lastFetch,
);
@@ -299,6 +335,7 @@ class Resource extends DataClass implements Insertable<Resource> {
..write('modified: $modified, ')
..write('size: $size, ')
..write('etag: $etag, ')
..write('contentType: $contentType, ')
..write('deleted: $deleted, ')
..write('lastFetch: $lastFetch')
..write(')'))
@@ -306,8 +343,8 @@ class Resource extends DataClass implements Insertable<Resource> {
}
@override
int get hashCode => Object.hash(
id, parent, name, dir, modified, size, etag, deleted, lastFetch);
int get hashCode => Object.hash(id, parent, name, dir, modified, size, etag,
contentType, deleted, lastFetch);
@override
bool operator ==(Object other) =>
identical(this, other) ||
@@ -319,6 +356,7 @@ class Resource extends DataClass implements Insertable<Resource> {
other.modified == this.modified &&
other.size == this.size &&
other.etag == this.etag &&
other.contentType == this.contentType &&
other.deleted == this.deleted &&
other.lastFetch == this.lastFetch);
}
@@ -331,6 +369,7 @@ class ResourcesCompanion extends UpdateCompanion<Resource> {
final Value<DateTime> modified;
final Value<int> size;
final Value<String> etag;
final Value<String> contentType;
final Value<bool> deleted;
final Value<DateTime?> lastFetch;
final Value<int> rowid;
@@ -342,6 +381,7 @@ class ResourcesCompanion extends UpdateCompanion<Resource> {
this.modified = const Value.absent(),
this.size = const Value.absent(),
this.etag = const Value.absent(),
this.contentType = const Value.absent(),
this.deleted = const Value.absent(),
this.lastFetch = const Value.absent(),
this.rowid = const Value.absent(),
@@ -354,6 +394,7 @@ class ResourcesCompanion extends UpdateCompanion<Resource> {
required DateTime modified,
required int size,
required String etag,
required String contentType,
this.deleted = const Value.absent(),
this.lastFetch = const Value.absent(),
this.rowid = const Value.absent(),
@@ -362,7 +403,8 @@ class ResourcesCompanion extends UpdateCompanion<Resource> {
dir = Value(dir),
modified = Value(modified),
size = Value(size),
etag = Value(etag);
etag = Value(etag),
contentType = Value(contentType);
static Insertable<Resource> custom({
Expression<String>? id,
Expression<String>? parent,
@@ -371,6 +413,7 @@ class ResourcesCompanion extends UpdateCompanion<Resource> {
Expression<DateTime>? modified,
Expression<int>? size,
Expression<String>? etag,
Expression<String>? contentType,
Expression<bool>? deleted,
Expression<DateTime>? lastFetch,
Expression<int>? rowid,
@@ -383,6 +426,7 @@ class ResourcesCompanion extends UpdateCompanion<Resource> {
if (modified != null) 'modified': modified,
if (size != null) 'size': size,
if (etag != null) 'etag': etag,
if (contentType != null) 'content_type': contentType,
if (deleted != null) 'deleted': deleted,
if (lastFetch != null) 'last_fetch': lastFetch,
if (rowid != null) 'rowid': rowid,
@@ -397,6 +441,7 @@ class ResourcesCompanion extends UpdateCompanion<Resource> {
Value<DateTime>? modified,
Value<int>? size,
Value<String>? etag,
Value<String>? contentType,
Value<bool>? deleted,
Value<DateTime?>? lastFetch,
Value<int>? rowid}) {
@@ -408,6 +453,7 @@ class ResourcesCompanion extends UpdateCompanion<Resource> {
modified: modified ?? this.modified,
size: size ?? this.size,
etag: etag ?? this.etag,
contentType: contentType ?? this.contentType,
deleted: deleted ?? this.deleted,
lastFetch: lastFetch ?? this.lastFetch,
rowid: rowid ?? this.rowid,
@@ -438,6 +484,9 @@ class ResourcesCompanion extends UpdateCompanion<Resource> {
if (etag.present) {
map['etag'] = Variable<String>(etag.value);
}
if (contentType.present) {
map['content_type'] = Variable<String>(contentType.value);
}
if (deleted.present) {
map['deleted'] = Variable<bool>(deleted.value);
}
@@ -460,6 +509,7 @@ class ResourcesCompanion extends UpdateCompanion<Resource> {
..write('modified: $modified, ')
..write('size: $size, ')
..write('etag: $etag, ')
..write('contentType: $contentType, ')
..write('deleted: $deleted, ')
..write('lastFetch: $lastFetch, ')
..write('rowid: $rowid')
@@ -487,6 +537,7 @@ typedef $$ResourcesTableCreateCompanionBuilder = ResourcesCompanion Function({
required DateTime modified,
required int size,
required String etag,
required String contentType,
Value<bool> deleted,
Value<DateTime?> lastFetch,
Value<int> rowid,
@@ -499,6 +550,7 @@ typedef $$ResourcesTableUpdateCompanionBuilder = ResourcesCompanion Function({
Value<DateTime> modified,
Value<int> size,
Value<String> etag,
Value<String> contentType,
Value<bool> deleted,
Value<DateTime?> lastFetch,
Value<int> rowid,
@@ -528,6 +580,7 @@ class $$ResourcesTableTableManager extends RootTableManager<
Value<DateTime> modified = const Value.absent(),
Value<int> size = const Value.absent(),
Value<String> etag = const Value.absent(),
Value<String> contentType = const Value.absent(),
Value<bool> deleted = const Value.absent(),
Value<DateTime?> lastFetch = const Value.absent(),
Value<int> rowid = const Value.absent(),
@@ -540,6 +593,7 @@ class $$ResourcesTableTableManager extends RootTableManager<
modified: modified,
size: size,
etag: etag,
contentType: contentType,
deleted: deleted,
lastFetch: lastFetch,
rowid: rowid,
@@ -552,6 +606,7 @@ class $$ResourcesTableTableManager extends RootTableManager<
required DateTime modified,
required int size,
required String etag,
required String contentType,
Value<bool> deleted = const Value.absent(),
Value<DateTime?> lastFetch = const Value.absent(),
Value<int> rowid = const Value.absent(),
@@ -564,6 +619,7 @@ class $$ResourcesTableTableManager extends RootTableManager<
modified: modified,
size: size,
etag: etag,
contentType: contentType,
deleted: deleted,
lastFetch: lastFetch,
rowid: rowid,
@@ -604,6 +660,11 @@ class $$ResourcesTableFilterComposer
builder: (column, joinBuilders) =>
ColumnFilters(column, joinBuilders: joinBuilders));
ColumnFilters<String> get contentType => $state.composableBuilder(
column: $state.table.contentType,
builder: (column, joinBuilders) =>
ColumnFilters(column, joinBuilders: joinBuilders));
ColumnFilters<bool> get deleted => $state.composableBuilder(
column: $state.table.deleted,
builder: (column, joinBuilders) =>
@@ -660,6 +721,11 @@ class $$ResourcesTableOrderingComposer
builder: (column, joinBuilders) =>
ColumnOrderings(column, joinBuilders: joinBuilders));
ColumnOrderings<String> get contentType => $state.composableBuilder(
column: $state.table.contentType,
builder: (column, joinBuilders) =>
ColumnOrderings(column, joinBuilders: joinBuilders));
ColumnOrderings<bool> get deleted => $state.composableBuilder(
column: $state.table.deleted,
builder: (column, joinBuilders) =>

View File

@@ -8,6 +8,7 @@ class Resources extends Table {
DateTimeColumn get modified => dateTime()();
IntColumn get size => integer()();
TextColumn get etag => text()();
TextColumn get contentType => text()();
BoolColumn get deleted => boolean().withDefault(const Constant(false))();
DateTimeColumn get lastFetch => dateTime().nullable()();

View File

@@ -53,6 +53,7 @@ class PhylumDatastore with AccountListener<PhylumApiResponse, PhylumApiErrorResp
modified: DateTime.parse(data['modified']),
size: data['size'],
etag: data['etag'],
contentType: data['ctype'] ?? '',
);
}
}

View File

@@ -41,7 +41,7 @@ class ResourceRepository {
return account.db.resources.select()..where((f) => f.id.isIn(ids));
}
Future<int> createResource(String id, bool dir, String parent, String name) {
Future<int> createResource(String id, bool dir, String parent, String name, String contentType) {
return account.db.resources.insertOne(ResourcesCompanion.insert(
id: id,
name: name,
@@ -50,6 +50,7 @@ class ResourceRepository {
modified: DateTime.now(),
size: 0,
etag: "",
contentType: contentType,
));
}

View File

@@ -430,7 +430,7 @@ packages:
source: hosted
version: "3.2.1"
http_parser:
dependency: transitive
dependency: "direct main"
description:
name: http_parser
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
@@ -558,7 +558,7 @@ packages:
source: hosted
version: "1.15.0"
mime:
dependency: transitive
dependency: "direct main"
description:
name: mime
sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2"

View File

@@ -17,19 +17,21 @@ dependencies:
hive:
http:
logger:
mime:
offtheline:
git:
url: https://codeberg.org/shroff/offtheline.git
ref: 7e4457c8e7f86662cd6d8424383423ceec7c06bb
state_notifier:
path:
path_provider:
provider:
state_notifier:
stream_transform:
super_clipboard:
uri:
uuid:
sqlite3: ^2.4.6
http_parser: ^4.0.2
dev_dependencies:
flutter_test: