Skip to content

Commit 1981735

Browse files
author
desperateCoder
committed
sync kinda syncs?
1 parent 26a7ab4 commit 1981735

81 files changed

Lines changed: 1550 additions & 453 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

app/cli/src/main/java/it/niedermann/nextcloud/deck/cli/commands/account/AccountCmd.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import java.util.logging.Level;
66
import java.util.logging.Logger;
77

8+
import io.reactivex.rxjava4.core.Maybe;
89
import io.reactivex.rxjava4.core.Single;
910
import it.niedermann.nextcloud.deck.cli.commands.account.subcommands.AccountAddCmd;
1011
import it.niedermann.nextcloud.deck.cli.commands.account.subcommands.AccountListCmd;
@@ -30,7 +31,7 @@ public class AccountCmd implements Callable<Integer> {
3031
@Override
3132
public Integer call() {
3233
try {
33-
final var account = Single.fromCompletionStage(getCurrentAccountUseCase.execute()).blockingGet();
34+
final var account = Maybe.fromCompletionStage(getCurrentAccountUseCase.execute()).toSingle().blockingGet();
3435
System.out.println(account);
3536
return 0;
3637

app/javafx/src/main/java/it/niedermann/nextcloud/deck/javafx/Launcher.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ static void main(String[] args) {
1414
if (args.length == 1 && "--purge".equals(args[0])) {
1515
// TODO Provide Purge-Button in ExceptionDialog
1616
appComponent.getPurgeService().purge();
17+
System.exit(0);
1718
}
1819

1920
JavaFxApplication.inject(appComponent.getFxComponentFactory());

app/javafx/src/main/java/it/niedermann/nextcloud/deck/javafx/services/application/PurgeService.java

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,31 @@ public void purge() {
4242
try {
4343
Platform.exit();
4444
database.close();
45-
Files.delete(dbPath);
46-
logger.info("✓ Deleted " + dbPath);
47-
} catch (IOException e) {
48-
logger.log(Level.SEVERE, "× Database file " + dbPath + " could not be deleted.", e);
45+
deleteFile(dbPath);
46+
deleteFile(dbPath.resolveSibling(dbPath.getFileName() + "-wal"));
47+
deleteFile(dbPath.resolveSibling(dbPath.getFileName() + "-shm"));
48+
deleteFile(dbPath.resolveSibling(dbPath.getFileName() + ".lck"));
49+
logger.info("✓ Purge completed for " + dbPath);
50+
} catch (Exception e) {
51+
logger.log(Level.SEVERE, "× Database files could not be fully deleted.", e);
52+
}
53+
}
54+
55+
private void deleteFile(Path path) {
56+
for (int i = 0; i < 5; i++) {
57+
try {
58+
if (Files.deleteIfExists(path)) {
59+
logger.info("✓ Deleted " + path);
60+
}
61+
return;
62+
} catch (IOException e) {
63+
logger.log(Level.WARNING, "× Could not delete " + path + " (attempt " + (i + 1) + "): " + e.getMessage());
64+
try {
65+
Thread.sleep(100);
66+
} catch (InterruptedException ignored) {
67+
Thread.currentThread().interrupt();
68+
}
69+
}
4970
}
5071
}
5172
}

app/javafx/src/main/java/it/niedermann/nextcloud/deck/javafx/ui/StageManager.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,12 @@ public StageManager(Stage stage,
7878
.subscribeOn(Schedulers.virtual())
7979
.observeOn(JavaFxScheduler.platform())
8080
.subscribe(hasAccounts -> {
81+
logger.info("StageManager :: hasAccounts changed: " + hasAccounts);
8182
if (hasAccounts) {
83+
if (controller.get() instanceof LoginScene) {
84+
logger.info("StageManager :: hasAccounts is true but LoginScene is active. Ignoring trigger, LoginScene will handle the transition.");
85+
return;
86+
}
8287
initialize();
8388
} else {
8489
showLogin();
@@ -87,6 +92,7 @@ public StageManager(Stage stage,
8792
}
8893

8994
protected CompletableFuture<Void> initialize() {
95+
logger.info("StageManager :: initialize()");
9096
return this.showSplashScreenScene()
9197
.thenApplyAsync(_ -> args)
9298
.thenComposeAsync(this::showContent)
@@ -95,17 +101,23 @@ protected CompletableFuture<Void> initialize() {
95101

96102
/// @return [CompletableFuture] - completed when the splashscreen is shown
97103
private CompletableFuture<Void> showSplashScreenScene() {
104+
logger.info("StageManager :: showSplashScreenScene()");
98105
final var bundle = inflater.inflate(splashScreenFactory.create());
99106
return this.setStageContent(bundle);
100107
}
101108

102109
/// @return [CompletableFuture] - completed when an account has successfully been imported
103-
protected CompletableFuture<Account.ID> showLogin() {
110+
protected CompletableFuture<Void> showLogin() {
111+
logger.info("StageManager :: showLogin()");
104112
final var accountImported = new CompletableFuture<Account.ID>();
105113
final var bundle = inflater.inflate(loginFactoryProvider.get().create(accountImported::complete));
106114
return this.setStageContent(bundle)
107115
.thenComposeAsync(_ -> accountImported)
108-
.thenComposeAsync(setCurrentAccountUseCase::execute);
116+
.thenComposeAsync(setCurrentAccountUseCase::execute)
117+
.thenComposeAsync(_ -> {
118+
logger.info("StageManager :: Login process complete, calling initialize()");
119+
return initialize();
120+
});
109121
}
110122

111123
/// @return [CompletableFuture] - completed when the content is visible
@@ -123,9 +135,11 @@ private CompletableFuture<Void> showErrorScene(Throwable throwable) {
123135
protected <T> CompletableFuture<Void> setStageContent(Inflater.FxBundle<T> controllerBundle) {
124136
final var cf = new CompletableFuture<Void>();
125137
final var controller = controllerBundle.controller();
138+
logger.info("StageManager :: setting content to " + controller.getClass().getSimpleName());
126139
final var oldCtrl = this.controller.getAndSet(controller);
127140

128141
if (oldCtrl instanceof Disposable oldDisposableCtrl && !oldDisposableCtrl.isDisposed()) {
142+
logger.info("StageManager :: disposing old controller " + oldDisposableCtrl.getClass().getSimpleName());
129143
oldDisposableCtrl.dispose();
130144
}
131145

app/javafx/src/main/java/it/niedermann/nextcloud/deck/javafx/ui/cellfactories/CardPreviewCellFactory.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package it.niedermann.nextcloud.deck.javafx.ui.cellfactories;
22

33
import io.reactivex.rxjava4.core.Flowable;
4+
import io.reactivex.rxjava4.core.Maybe;
45
import io.reactivex.rxjava4.disposables.CompositeDisposable;
56
import it.niedermann.nextcloud.deck.domain.model.Account;
67
import it.niedermann.nextcloud.deck.domain.model.query.PreviewCard;
@@ -43,7 +44,8 @@ public CardPreviewCellFactory(GetCurrentAccountUseCase getCurrentAccountUseCase,
4344
this.keyValueStore = keyValueStore;
4445
this.colorUtil = colorUtil;
4546

46-
disposables.add(Flowable.fromCompletionStage(getCurrentAccountUseCase.execute())
47+
disposables.add(Maybe.fromCompletionStage(getCurrentAccountUseCase.execute())
48+
.toFlowable()
4749
.switchMap(id -> Flowable.fromPublisher(getAccountUseCase.execute(id)))
4850
.observeOn(JavaFxScheduler.platform())
4951
.subscribe(account -> this.currentAccount = account));

app/javafx/src/main/java/it/niedermann/nextcloud/deck/javafx/ui/controller/scenes/LoginScene.java

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import dagger.assisted.AssistedFactory;
1919
import dagger.assisted.AssistedInject;
2020
import io.reactivex.rxjava4.core.Flowable;
21+
import io.reactivex.rxjava4.core.Maybe;
2122
import io.reactivex.rxjava4.core.Single;
2223
import io.reactivex.rxjava4.processors.BehaviorProcessor;
2324
import io.reactivex.rxjava4.processors.FlowableProcessor;
@@ -133,21 +134,25 @@ public void initialize(URL location, ResourceBundle resources) {
133134

134135
public void submit() {
135136

137+
logger.info("Submit clicked, starting import process...");
136138
importInProgress.onNext(true);
137139

138140
final var currentlyImportingAccountId = new AtomicReference<Account.ID>();
139141

140-
final var syncStatusDisposable = Single.fromCompletionStage(
142+
final var syncStatusDisposable = Maybe.fromCompletionStage(
141143
authenticateAccount(
142144
this.url.getText(),
143145
this.username.getText(),
144146
this.password.getText()))
145-
146-
.flatMapPublisher(authenticatedAccount ->
147-
importAccountUseCase.execute(
148-
authenticatedAccount.url(),
149-
authenticatedAccount.username(),
150-
authenticatedAccount.token()))
147+
.toSingle()
148+
149+
.flatMapPublisher(authenticatedAccount -> {
150+
logger.info("Authentication successful, importing account: " + authenticatedAccount.username());
151+
return importAccountUseCase.execute(
152+
authenticatedAccount.url(),
153+
authenticatedAccount.username(),
154+
authenticatedAccount.token());
155+
})
151156

152157
.observeOn(JavaFxScheduler.platform())
153158

@@ -159,6 +164,7 @@ public void submit() {
159164

160165
.doOnError(throwable -> {
161166

167+
logger.log(Level.WARNING, "Import failed", throwable);
162168
importInProgress.onNext(false);
163169

164170
if (throwable.getCause() instanceof SQLiteException) {
@@ -170,8 +176,16 @@ public void submit() {
170176
})
171177
.ignoreElements()
172178
.observeOn(JavaFxScheduler.platform())
173-
.doFinally(() -> importInProgress.onNext(false))
174-
.subscribe(() -> viewModel.onAccountImported(currentlyImportingAccountId.get()));
179+
.doFinally(() -> {
180+
logger.info("Import process finished (finally)");
181+
importInProgress.onNext(false);
182+
})
183+
.subscribe(() -> {
184+
logger.info("Import process completed successfully for account: " + currentlyImportingAccountId.get());
185+
viewModel.onAccountImported(currentlyImportingAccountId.get());
186+
}, throwable -> {
187+
logger.log(Level.SEVERE, "Unexpected error in import chain", throwable);
188+
});
175189

176190
addDisposable(syncStatusDisposable);
177191
}

app/javafx/src/main/java/it/niedermann/nextcloud/deck/javafx/ui/controller/views/AvatarView.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import org.kordamp.ikonli.javafx.FontIcon;
44

55
import java.io.ByteArrayInputStream;
6+
import java.util.Objects;
67
import java.util.concurrent.CompletableFuture;
78
import java.util.logging.Level;
89
import java.util.logging.Logger;
@@ -49,13 +50,16 @@ public AvatarView() {
4950
fitWidthProperty().addListener((_, _, newValue) -> sizeProcessor.onNext(newValue.doubleValue()));
5051

5152
Flowable.combineLatest(
52-
requestProcessor,
53-
sizeProcessor,
53+
requestProcessor.distinctUntilChanged((r1, r2) ->
54+
Objects.equals(r1.account(), r2.account()) &&
55+
Objects.equals(r1.userId(), r2.userId())
56+
),
57+
sizeProcessor.distinctUntilChanged().filter(size -> size > 0),
5458
RequestSize::new
5559
).subscribe(newValue -> loadImage(newValue.request(), newValue.size()));
5660
}
5761

58-
private record Request(Account account, User.ID userId, CompletableFuture<Void> onLoaded) {
62+
private record Request(Account account, it.niedermann.nextcloud.deck.domain.model.User.ID userId, CompletableFuture<Void> onLoaded) {
5963
}
6064

6165
private record RequestSize(Request request, double size) {

app/shared/src/main/java/it/niedermann/nextcloud/deck/app/shared/args/board/BoardArgResolver.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public CompletableFuture<BoardParsedArgs> resolve(BoardRawArgs args) {
4040
.flatMapSingle(hasAccounts -> {
4141
// TODO No need to check for hasAccounts, better check fo accounts.exist(args)
4242
if (hasAccounts) {
43-
return Single.fromCompletionStage(getCurrentAccountUseCase.execute());
43+
return Maybe.fromCompletionStage(getCurrentAccountUseCase.execute()).toSingle();
4444
}
4545

4646
return Single.error(new BoardArgResolver.NoAccountConfiguredException());

app/shared/src/main/java/it/niedermann/nextcloud/deck/app/shared/di/modules/LocalModule.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,19 @@
55
import it.niedermann.nextcloud.deck.data.local.DeckDatabase;
66
import it.niedermann.nextcloud.deck.data.local.dao.AccessControlDao;
77
import it.niedermann.nextcloud.deck.data.local.dao.AccountDao;
8+
import it.niedermann.nextcloud.deck.data.local.dao.ActivityDao;
89
import it.niedermann.nextcloud.deck.data.local.dao.AttachmentDao;
910
import it.niedermann.nextcloud.deck.data.local.dao.BoardDao;
1011
import it.niedermann.nextcloud.deck.data.local.dao.CardDao;
1112
import it.niedermann.nextcloud.deck.data.local.dao.ColumnDao;
1213
import it.niedermann.nextcloud.deck.data.local.dao.CommentDao;
14+
import it.niedermann.nextcloud.deck.data.local.dao.JoinBoardWithLabelDao;
15+
import it.niedermann.nextcloud.deck.data.local.dao.JoinBoardWithPermissionDao;
16+
import it.niedermann.nextcloud.deck.data.local.dao.JoinBoardWithUserDao;
17+
import it.niedermann.nextcloud.deck.data.local.dao.JoinCardWithLabelDao;
18+
import it.niedermann.nextcloud.deck.data.local.dao.JoinCardWithUserDao;
1319
import it.niedermann.nextcloud.deck.data.local.dao.LabelDao;
20+
import it.niedermann.nextcloud.deck.data.local.dao.UserDao;
1421
import jakarta.inject.Singleton;
1522

1623
@Module
@@ -63,4 +70,46 @@ public CommentDao provideCommentDao(DeckDatabase deckDatabase) {
6370
public AccessControlDao provideAccessControlDao(DeckDatabase deckDatabase) {
6471
return deckDatabase.getAccessControlDao();
6572
}
73+
74+
@Provides
75+
@Singleton
76+
public JoinBoardWithLabelDao provideJoinBoardWithLabelDao(DeckDatabase deckDatabase) {
77+
return deckDatabase.getJoinBoardWithLabelDao();
78+
}
79+
80+
@Provides
81+
@Singleton
82+
public JoinBoardWithPermissionDao provideJoinBoardWithPermissionDao(DeckDatabase deckDatabase) {
83+
return deckDatabase.getJoinBoardWithPermissionDao();
84+
}
85+
86+
@Provides
87+
@Singleton
88+
public JoinBoardWithUserDao provideJoinBoardWithUserDao(DeckDatabase deckDatabase) {
89+
return deckDatabase.getJoinBoardWithUserDao();
90+
}
91+
92+
@Provides
93+
@Singleton
94+
public JoinCardWithLabelDao provideJoinCardWithLabelDao(DeckDatabase deckDatabase) {
95+
return deckDatabase.getJoinCardWithLabelDao();
96+
}
97+
98+
@Provides
99+
@Singleton
100+
public JoinCardWithUserDao provideJoinCardWithUserDao(DeckDatabase deckDatabase) {
101+
return deckDatabase.getJoinCardWithUserDao();
102+
}
103+
104+
@Provides
105+
@Singleton
106+
public UserDao provideUserDao(DeckDatabase deckDatabase) {
107+
return deckDatabase.getUserDao();
108+
}
109+
110+
@Provides
111+
@Singleton
112+
public ActivityDao provideActivityDao(DeckDatabase deckDatabase) {
113+
return deckDatabase.getActivityDao();
114+
}
66115
}

app/shared/src/main/java/it/niedermann/nextcloud/deck/app/shared/di/modules/MapperModule.java

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,16 @@
22

33
import dagger.Module;
44
import dagger.Provides;
5+
import it.niedermann.nextcloud.deck.data.local.mapper.AccessControlMapper;
56
import it.niedermann.nextcloud.deck.data.local.mapper.AccountMapper;
7+
import it.niedermann.nextcloud.deck.data.local.mapper.ActivityMapper;
8+
import it.niedermann.nextcloud.deck.data.local.mapper.AttachmentMapper;
9+
import it.niedermann.nextcloud.deck.data.local.mapper.BoardMapper;
10+
import it.niedermann.nextcloud.deck.data.local.mapper.CardMapper;
11+
import it.niedermann.nextcloud.deck.data.local.mapper.ColumnMapper;
12+
import it.niedermann.nextcloud.deck.data.local.mapper.CommentMapper;
13+
import it.niedermann.nextcloud.deck.data.local.mapper.LabelMapper;
14+
import it.niedermann.nextcloud.deck.data.local.mapper.UserMapper;
615
import jakarta.inject.Singleton;
716

817
@Module
@@ -13,5 +22,59 @@ public class MapperModule {
1322
AccountMapper provideAccountMapper() {
1423
return AccountMapper.INSTANCE;
1524
}
16-
25+
26+
@Provides
27+
@Singleton
28+
BoardMapper provideBoardMapper() {
29+
return BoardMapper.INSTANCE;
30+
}
31+
32+
@Provides
33+
@Singleton
34+
ColumnMapper provideColumnMapper() {
35+
return ColumnMapper.INSTANCE;
36+
}
37+
38+
@Provides
39+
@Singleton
40+
CardMapper provideCardMapper() {
41+
return CardMapper.INSTANCE;
42+
}
43+
44+
@Provides
45+
@Singleton
46+
LabelMapper provideLabelMapper() {
47+
return LabelMapper.INSTANCE;
48+
}
49+
50+
@Provides
51+
@Singleton
52+
AttachmentMapper provideAttachmentMapper() {
53+
return AttachmentMapper.INSTANCE;
54+
}
55+
56+
@Provides
57+
@Singleton
58+
CommentMapper provideCommentMapper() {
59+
return CommentMapper.INSTANCE;
60+
}
61+
62+
@Provides
63+
@Singleton
64+
AccessControlMapper provideAccessControlMapper() {
65+
return AccessControlMapper.INSTANCE;
66+
}
67+
68+
@Provides
69+
@Singleton
70+
ActivityMapper provideActivityMapper() {
71+
return ActivityMapper.INSTANCE;
72+
}
73+
74+
@Provides
75+
@Singleton
76+
UserMapper provideUserMapper() {
77+
return UserMapper.INSTANCE;
78+
}
79+
1780
}

0 commit comments

Comments
 (0)