diff --git a/ModerationClient/ViewModels/ClientViewModel.cs b/ModerationClient/ViewModels/ClientViewModel.cs
new file mode 100644
index 0000000..340eb56
--- /dev/null
+++ b/ModerationClient/ViewModels/ClientViewModel.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Threading.Tasks;
+using ArcaneLibs.Collections;
+using LibMatrix.Helpers;
+using LibMatrix.Responses;
+using Microsoft.Extensions.Logging;
+using ModerationClient.Services;
+
+namespace ModerationClient.ViewModels;
+
+public partial class ClientViewModel : ViewModelBase
+{
+ public ClientViewModel(ILogger<ClientViewModel> logger, MatrixAuthenticationService authService) {
+ this.logger = logger;
+ this.authService = authService;
+ _ = Task.Run(Run);
+ }
+
+ private readonly ILogger<ClientViewModel> logger;
+ private readonly MatrixAuthenticationService authService;
+
+ private Exception? _exception;
+
+ public Exception? Exception {
+ get => _exception;
+ private set => SetProperty(ref _exception, value);
+ }
+
+ public ObservableCollection<SpaceNode> DisplayedSpaces { get; } = [
+ new SpaceNode { Name = "Root", Children = [
+ new SpaceNode { Name = "Child 1" },
+ new SpaceNode { Name = "Child 2" },
+ new SpaceNode { Name = "Child 3" }
+ ] },
+ new SpaceNode { Name = "Root 2", Children = [
+ new SpaceNode { Name = "Child 4" },
+ new SpaceNode { Name = "Child 5" },
+ new SpaceNode { Name = "Child 6" }
+ ] }
+ ];
+
+ public async Task Run() {
+ var sh = new SyncStateResolver(authService.Homeserver, logger);
+ // var res = await sh.SyncAsync();
+ while (true) {
+ var res = await sh.ContinueAsync();
+ Console.WriteLine("mow");
+ }
+ }
+
+ private void ApplySpaceChanges(SyncResponse newSync) {
+ List<string> handledRoomIds = [];
+
+ }
+}
+
+public class SpaceNode {
+ public string Name { get; set; }
+ public ObservableCollection<SpaceNode> Children { get; set; } = [];
+}
\ No newline at end of file
diff --git a/ModerationClient/ViewModels/LoginViewModel.cs b/ModerationClient/ViewModels/LoginViewModel.cs
new file mode 100644
index 0000000..32f0d6e
--- /dev/null
+++ b/ModerationClient/ViewModels/LoginViewModel.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Threading.Tasks;
+using ModerationClient.Services;
+
+namespace ModerationClient.ViewModels;
+
+public partial class LoginViewModel(MatrixAuthenticationService authService) : ViewModelBase
+{
+ private Exception? _exception;
+ public string Username { get; set; }
+ public string Password { get; set; }
+
+ public Exception? Exception {
+ get => _exception;
+ private set => SetProperty(ref _exception, value);
+ }
+
+ public async Task LoginAsync() {
+ try {
+ Exception = null;
+ await authService.LoginAsync(Username, Password);
+ } catch (Exception e) {
+ Exception = e;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ModerationClient/ViewModels/MainWindowViewModel.cs b/ModerationClient/ViewModels/MainWindowViewModel.cs
new file mode 100644
index 0000000..01ec6d6
--- /dev/null
+++ b/ModerationClient/ViewModels/MainWindowViewModel.cs
@@ -0,0 +1,33 @@
+using System;
+using ModerationClient.Services;
+using ModerationClient.Views;
+
+namespace ModerationClient.ViewModels;
+
+public partial class MainWindowViewModel(MatrixAuthenticationService authService, CommandLineConfiguration cfg) : ViewModelBase {
+ public MainWindow? MainWindow { get; set; }
+
+ private float _scale = 1.0f;
+ private ViewModelBase _currentViewModel = new LoginViewModel(authService);
+
+ public ViewModelBase CurrentViewModel {
+ get => _currentViewModel;
+ set => SetProperty(ref _currentViewModel, value);
+ }
+
+ public CommandLineConfiguration CommandLineConfiguration { get; } = cfg;
+ public MatrixAuthenticationService AuthService { get; } = authService;
+
+ public float Scale {
+ get => _scale;
+ set {
+ SetProperty(ref _scale, (float)Math.Round(value, 2));
+ OnPropertyChanged(nameof(ChildTargetWidth));
+ OnPropertyChanged(nameof(ChildTargetHeight));
+ }
+ }
+ public int ChildTargetWidth => (int)(MainWindow?.Width / Scale ?? 1);
+ public int ChildTargetHeight => (int)(MainWindow?.Height / Scale ?? 1);
+
+
+}
\ No newline at end of file
diff --git a/ModerationClient/ViewModels/ViewModelBase.cs b/ModerationClient/ViewModels/ViewModelBase.cs
new file mode 100644
index 0000000..0137aaf
--- /dev/null
+++ b/ModerationClient/ViewModels/ViewModelBase.cs
@@ -0,0 +1,7 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+
+namespace ModerationClient.ViewModels;
+
+public class ViewModelBase : ObservableObject
+{
+}
\ No newline at end of file
|