2019-07-19 10:30:41 +10:00
|
|
|
# Copyright 2019 miruka
|
|
|
|
# This file is part of harmonyqml, licensed under LGPLv3.
|
|
|
|
|
|
|
|
import asyncio
|
|
|
|
import json
|
|
|
|
from pathlib import Path
|
|
|
|
from typing import Any, Dict
|
|
|
|
|
|
|
|
import aiofiles
|
|
|
|
from dataclasses import dataclass, field
|
|
|
|
|
|
|
|
from .backend import Backend
|
|
|
|
|
2019-07-19 11:58:21 +10:00
|
|
|
JsonData = Dict[str, Any]
|
|
|
|
|
2019-07-19 10:30:41 +10:00
|
|
|
WRITE_LOCK = asyncio.Lock()
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
class ConfigFile:
|
2019-07-21 21:14:16 +10:00
|
|
|
backend: Backend = field(repr=False)
|
2019-07-21 20:05:01 +10:00
|
|
|
filename: str = field()
|
|
|
|
use_data_dir: bool = False
|
2019-07-19 10:30:41 +10:00
|
|
|
|
|
|
|
@property
|
|
|
|
def path(self) -> Path:
|
|
|
|
# pylint: disable=no-member
|
2019-07-21 20:05:01 +10:00
|
|
|
dirs = self.backend.app.appdirs
|
|
|
|
to = dirs.user_data_dir if self.use_data_dir else dirs.user_config_dir
|
|
|
|
return Path(to) / self.filename
|
2019-07-19 10:30:41 +10:00
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
class JSONConfigFile(ConfigFile):
|
2019-07-19 11:58:21 +10:00
|
|
|
async def default_data(self) -> JsonData:
|
|
|
|
return {}
|
|
|
|
|
|
|
|
|
|
|
|
async def read(self) -> JsonData:
|
2019-07-19 10:30:41 +10:00
|
|
|
try:
|
2019-07-21 23:24:11 +10:00
|
|
|
data = json.loads(self.path.read_text())
|
2019-07-19 10:30:41 +10:00
|
|
|
except (json.JSONDecodeError, FileNotFoundError):
|
2019-07-21 23:24:11 +10:00
|
|
|
data = {}
|
|
|
|
|
|
|
|
return {**await self.default_data(), **data}
|
2019-07-19 10:30:41 +10:00
|
|
|
|
|
|
|
|
2019-07-19 11:58:21 +10:00
|
|
|
async def write(self, data: JsonData) -> None:
|
2019-07-19 10:30:41 +10:00
|
|
|
js = json.dumps(data, indent=4, ensure_ascii=False, sort_keys=True)
|
|
|
|
|
|
|
|
async with WRITE_LOCK:
|
|
|
|
self.path.parent.mkdir(parents=True, exist_ok=True)
|
|
|
|
|
|
|
|
async with aiofiles.open(self.path, "w") as new:
|
|
|
|
await new.write(js)
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
class Accounts(JSONConfigFile):
|
|
|
|
filename: str = "accounts.json"
|
|
|
|
|
|
|
|
async def any_saved(self) -> bool:
|
|
|
|
return bool(await self.read())
|
|
|
|
|
|
|
|
|
|
|
|
async def add(self, user_id: str) -> None:
|
|
|
|
# pylint: disable=no-member
|
|
|
|
client = self.backend.clients[user_id]
|
|
|
|
|
|
|
|
await self.write({
|
|
|
|
**await self.read(),
|
|
|
|
client.user_id: {
|
|
|
|
"homeserver": client.homeserver,
|
|
|
|
"token": client.access_token,
|
|
|
|
"device_id": client.device_id,
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
async def delete(self, user_id: str) -> None:
|
|
|
|
await self.write({
|
|
|
|
uid: info
|
|
|
|
for uid, info in (await self.read()).items() if uid != user_id
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
class UISettings(JSONConfigFile):
|
|
|
|
filename: str = "ui-settings.json"
|
2019-07-19 11:58:21 +10:00
|
|
|
|
|
|
|
async def default_data(self) -> JsonData:
|
|
|
|
return {
|
2019-07-21 22:57:17 +10:00
|
|
|
"writeAliases": {}
|
2019-07-19 11:58:21 +10:00
|
|
|
}
|
2019-07-21 20:05:01 +10:00
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
class UIState(JSONConfigFile):
|
|
|
|
filename: str = "ui-state.json"
|
|
|
|
use_data_dir: bool = True
|
|
|
|
|
|
|
|
async def default_data(self) -> JsonData:
|
|
|
|
return {
|
2019-07-21 23:24:11 +10:00
|
|
|
"collapseAccounts": {},
|
|
|
|
"collapseCategories": {},
|
2019-07-21 23:08:22 +10:00
|
|
|
"page": "Pages/Default.qml",
|
|
|
|
"pageProperties": {},
|
|
|
|
"sidePaneManualWidth": None,
|
2019-07-21 20:05:01 +10:00
|
|
|
}
|