Skip to content

Commit

Permalink
Merge pull request #772 from LinwoodDev/feature/password-notes
Browse files Browse the repository at this point in the history
Add password protected notes, closes #771
  • Loading branch information
CodeDoctorDE authored Dec 27, 2024
2 parents 097c7b1 + 675ddb6 commit 929e015
Show file tree
Hide file tree
Showing 125 changed files with 1,301 additions and 1,171 deletions.
16 changes: 16 additions & 0 deletions api/lib/src/converter/color.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import 'package:dart_leap/dart_leap.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

class ColorJsonConverter extends JsonConverter<SRGBColor, int> {
const ColorJsonConverter();

@override
SRGBColor fromJson(int json) {
return SRGBColor(json);
}

@override
int toJson(SRGBColor object) {
return object.value;
}
}
14 changes: 7 additions & 7 deletions api/lib/src/converter/note.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@ import '../../butterfly_api.dart';

const kArchiveSignature = 0x50;

NoteData noteDataMigrator(Uint8List data) {
NoteData noteDataMigrator(Uint8List data, {String? password}) {
Archive archive;
if (data.isNotEmpty && data[0] != kArchiveSignature) {
final map = json.decode(utf8.decode(data)) as Map<String, dynamic>;
archive = convertLegacyDataToArchive(map);
} else {
archive = ZipDecoder().decodeBytes(data);
archive = ZipDecoder().decodeBytes(data, password: password);
}
return archiveNoteDataMigrator(archive);
return archiveNoteDataMigrator(archive, password: password);
}

NoteData archiveNoteDataMigrator(Archive archive) {
var noteData = NoteData(archive);
NoteData archiveNoteDataMigrator(Archive archive, {String? password}) {
var noteData = NoteData.build(archive, password: password);
var metadata = noteData.getMetadata();
if (metadata != null &&
(metadata.fileVersion ?? kFileVersion) < kFileVersion) {
Expand Down Expand Up @@ -52,7 +52,7 @@ NoteData _migrate(NoteData noteData, FileMetadata metadata) {
}
}
if (version < 10) {
for (final page in noteData.getAssets(kPagesArchiveDirectory)) {
for (final page in noteData.getAssets('$kPagesArchiveDirectory/')) {
final data = noteData.getAsset('$kPagesArchiveDirectory/$page');
if (data == null) continue;
final pageData = json.decode(utf8.decode(data)) as Map<String, dynamic>;
Expand Down Expand Up @@ -89,7 +89,7 @@ NoteData _migrate(NoteData noteData, FileMetadata metadata) {
}
}
if (version < 11) {
for (final page in noteData.getAssets(kPagesArchiveDirectory)) {
for (final page in noteData.getAssets('$kPagesArchiveDirectory/')) {
final data = noteData.getAsset('$kPagesArchiveDirectory/$page');
if (data == null) continue;
final pageData = json.decode(utf8.decode(data)) as Map<String, dynamic>;
Expand Down
17 changes: 8 additions & 9 deletions api/lib/src/converter/xopp.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'dart:typed_data';
import 'package:archive/archive.dart';
import 'package:butterfly_api/butterfly_api.dart';
import 'package:butterfly_api/butterfly_text.dart' as text;
import 'package:dart_leap/dart_leap.dart';
import 'package:xml/xml.dart';

List<PathPoint> toPoints(List<double> data) {
Expand All @@ -20,14 +21,12 @@ List<PathPoint> toPoints(List<double> data) {
return points;
}

int _importColor(String value) {
final number = int.parse(value.substring(1), radix: 16);
return (number >> 8 | number << 24);
SRGBColor _importColor(String value) {
return SRGBColor.parse(value);
}

String _exportColor(int value) {
final number = (value >> 8 | value << 24);
return '#${number.toRadixString(16)}';
String _exportColor(SRGBColor value) {
return value.toHexString();
}

(NoteData, PadElement?) getElement(
Expand Down Expand Up @@ -161,8 +160,8 @@ Uint8List xoppExporter(NoteData document) {
builder.element('page', nest: () {
builder.element('background', attributes: {
'type': 'solid',
'color':
_exportColor(page.backgrounds.firstOrNull?.defaultColor ?? 0),
'color': _exportColor(
page.backgrounds.firstOrNull?.defaultColor ?? SRGBColor.white),
'style': 'plain',
});
builder.element('layer', nest: () {
Expand All @@ -185,7 +184,7 @@ Uint8List xoppExporter(NoteData document) {
?.span
: styleSheet?.getParagraphProperty('p')?.span;
builder.element('text', attributes: {
'color': _exportColor(style?.color ?? 0),
'color': _exportColor(style?.color ?? SRGBColor.black),
'size': (style?.size ?? 12).toString(),
'x': e.position.x.toString(),
'y': e.position.y.toString(),
Expand Down
8 changes: 0 additions & 8 deletions api/lib/src/models/asset.dart
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
import 'dart:typed_data';

import 'package:butterfly_api/butterfly_api.dart';
import 'package:lw_file_system_api/lw_file_system_api.dart';

enum AssetFileType { note, page, image, markdown, pdf, svg, xopp, archive }

extension AppDocumentLoadExtension on FileSystemFile {
NoteData load({bool disableMigrations = false}) =>
NoteData.fromData(Uint8List.fromList(data),
disableMigrations: disableMigrations);
}

extension AssetLocationFileTypeExtension on AssetLocation {
AssetFileType? get fileType =>
AssetFileTypeHelper.fromFileExtension(fileExtension);
Expand Down
6 changes: 3 additions & 3 deletions api/lib/src/models/background.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'package:dart_leap/dart_leap.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

import 'colors.dart';
import 'texture.dart';

part 'background.g.dart';
Expand Down Expand Up @@ -36,8 +36,8 @@ sealed class Background with _$Background {
factory Background.fromJson(Map<String, dynamic> json) =>
_$BackgroundFromJson(json);

int get defaultColor => switch (this) {
SRGBColor get defaultColor => switch (this) {
TextureBackground e => e.texture.boxColor,
_ => BasicColors.white
_ => SRGBColor.white
};
}
13 changes: 6 additions & 7 deletions api/lib/src/models/colors.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import 'package:dart_leap/dart_leap.dart';

class BasicColors {
static const white = 0xFFFFFFFF;
static const light = 0xFFD9D9D9;
static const black = 0xFF000000;
static const dark = 0xFF1A1A1A;
static const red = 0xFFF44336;
static const blue = 0xFF2196F3;
static const transparent = 0x00000000;
static const light = SRGBColor(0xFFD9D9D9);
static const dark = SRGBColor(0xFF1A1A1A);
static const red = SRGBColor(0xFFF44336);
static const blue = SRGBColor(0xFF2196F3);

const BasicColors._();
}
59 changes: 45 additions & 14 deletions api/lib/src/models/data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,56 @@ import 'palette.dart';

final Set<String> validAssetPaths = {kImagesArchiveDirectory};

@immutable
final class NoteFile {
final Uint8List data;

NoteFile(this.data);

bool isEncrypted() => isZipEncrypted(data);

(String?, NoteData)? _data;

NoteData? load({String? password}) {
if (_data != null && _data?.$1 == password) {
return _data?.$2;
}
try {
final data = NoteData.fromData(this.data, password: password);
_data = (password, data);
return data;
} catch (_) {
return null;
}
}
}

final class NoteData extends ArchiveData<NoteData> {
NoteData(super.archive, {super.state});
NoteData.build(super.archive, {super.password}) : super.build();

factory NoteData.fromData(Uint8List data, {bool disableMigrations = false}) {
factory NoteData.fromData(Uint8List data,
{bool disableMigrations = false, String? password}) {
if (disableMigrations) {
final archive = ZipDecoder().decodeBytes(data);
return NoteData(archive);
final archive = ZipDecoder().decodeBytes(data, password: password);
return NoteData.build(archive, password: password);
}
return noteDataMigrator(data);
return noteDataMigrator(data, password: password);
}

factory NoteData.fromArchive(Archive archive,
{bool disableMigrations = false}) {
{bool disableMigrations = false, String? password}) {
if (disableMigrations) {
return NoteData(archive);
return NoteData.build(archive, password: password);
}
return archiveNoteDataMigrator(archive);
}

factory NoteData.fromJson(dynamic json) => NoteData.fromData(
factory NoteData.fromJson(dynamic json,
{bool disableMigrations = false, String? password}) =>
NoteData.fromData(
base64Decode(json as String),
disableMigrations: disableMigrations,
password: password,
);

NoteFileType? get type => getMetadata()?.type;
Expand Down Expand Up @@ -71,7 +99,7 @@ final class NoteData extends ArchiveData<NoteData> {
'$name${fileExtension.isNotEmpty ? '.$fileExtension' : ''}';

String findUniqueName(String path, String fileExtension, [String name = '']) {
final assets = getAssets(path);
final assets = getAssets('$path/');
if (!assets.contains(_getFileName(name, fileExtension)) &&
name.trim().isNotEmpty) {
return _getFileName(name, fileExtension);
Expand Down Expand Up @@ -238,7 +266,7 @@ final class NoteData extends ArchiveData<NoteData> {

@useResult
List<(int, String, String)> _getPagesOrder() =>
getAssets(kPagesArchiveDirectory, true).map((e) {
getAssets('$kPagesArchiveDirectory/', true).map((e) {
if (e.contains('.')) {
final split = e.split('.');
return (
Expand Down Expand Up @@ -319,13 +347,13 @@ final class NoteData extends ArchiveData<NoteData> {
removeAsset('$kPacksArchiveDirectory/$name.bfly');

@useResult
Iterable<String> getPacks() => getAssets(kPacksArchiveDirectory, true);
Iterable<String> getPacks() => getAssets('$kPacksArchiveDirectory/', true);

// Pack specific

@useResult
Iterable<String> getComponents() =>
getAssets(kComponentsArchiveDirectory, true);
getAssets('$kComponentsArchiveDirectory/', true);

@useResult
ButterflyComponent? getComponent(String componentName) {
Expand All @@ -348,7 +376,7 @@ final class NoteData extends ArchiveData<NoteData> {
removeAsset('$kComponentsArchiveDirectory/$name.json');

@useResult
Iterable<String> getStyles() => getAssets(kStylesArchiveDirectory, true);
Iterable<String> getStyles() => getAssets('$kStylesArchiveDirectory/', true);

@useResult
TextStyleSheet? getStyle(String styleName) {
Expand Down Expand Up @@ -383,7 +411,8 @@ final class NoteData extends ArchiveData<NoteData> {
}

@useResult
Iterable<String> getPalettes() => getAssets(kPalettesArchiveDirectory, true);
Iterable<String> getPalettes() =>
getAssets('$kPalettesArchiveDirectory/', true);

@useResult
ColorPalette? getPalette(String paletteName) {
Expand Down Expand Up @@ -425,4 +454,6 @@ final class NoteData extends ArchiveData<NoteData> {
final removed = Set<String>.from(state.removed)..remove(path);
return updateState(state.copyWith(removed: removed));
}

NoteFile toFile() => NoteFile(exportAsBytes());
}
10 changes: 6 additions & 4 deletions api/lib/src/models/element.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import 'dart:math';

import 'package:butterfly_api/src/converter/color.dart';
import 'package:dart_leap/dart_leap.dart';

import '../converter/core.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

import '../converter/id.dart';
import 'colors.dart';
import 'pack.dart';
import 'point.dart';
import 'property.dart';
Expand Down Expand Up @@ -60,7 +62,7 @@ mixin LabelElement {
double get scale;
PackAssetLocation get styleSheet;
ElementConstraint get constraint;
int get foreground;
SRGBColor get foreground;

AreaProperty get areaProperty => switch (this) {
MarkdownElement e => e.areaProperty,
Expand Down Expand Up @@ -102,7 +104,7 @@ sealed class PadElement with _$PadElement {
@Default(PackAssetLocation()) PackAssetLocation styleSheet,
required TextArea area,
@Default(ElementConstraint(size: 1000)) ElementConstraint constraint,
@Default(BasicColors.black) int foreground,
@Default(SRGBColor.black) @ColorJsonConverter() SRGBColor foreground,
@Default({}) Map<String, dynamic> extra,
}) = TextElement;

Expand All @@ -119,7 +121,7 @@ sealed class PadElement with _$PadElement {
@Default(AreaProperty()) AreaProperty areaProperty,
required String text,
@Default(ElementConstraint(size: 1000)) ElementConstraint constraint,
@Default(BasicColors.black) int foreground,
@Default(SRGBColor.black) @ColorJsonConverter() SRGBColor foreground,
@Default({}) Map<String, dynamic> extra,
}) = MarkdownElement;

Expand Down
Loading

0 comments on commit 929e015

Please sign in to comment.