Implement profiles for the Content server viewer

Fixes #1979022 [[Feature Request] Import/Export setting file for Content Server Viewer](https://bugs.launchpad.net/calibre/+bug/1979022)
This commit is contained in:
Kovid Goyal 2024-02-21 22:57:08 +05:30
parent 7a1a26f2e3
commit 9bc695c843
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 52 additions and 5 deletions

View File

@ -89,23 +89,19 @@ def expand_profile_user_names(user_names):
return user_names
def load_viewer_profiles(*user_names: str, as_json_string=False):
def load_viewer_profiles(*user_names: str):
user_names = expand_profile_user_names(user_names)
ans = {}
try:
with open(os.path.join(viewer_config_dir, 'profiles.json'), 'rb') as f:
raw = json.loads(f.read())
except FileNotFoundError:
if as_json_string:
return '{}'
return ans
for uname, profiles in raw.items():
if uname in user_names:
for profile_name, profile in profiles.items():
if profile_name not in ans or ans[profile_name]['__timestamp__'] <= profile['__timestamp__']:
ans[profile_name] = profile
if as_json_string:
return json.dumps(ans)
return ans

View File

@ -318,6 +318,32 @@ def reader_background(ctx, rd, encoded_fname):
raise HTTPNotFound(f'Reader background {encoded_fname} not found')
@endpoint('/reader-profiles/get-all', postprocess=json)
def get_all_reader_profiles(ctx, rd):
from calibre.gui2.viewer.config import load_viewer_profiles
which = 'user:'
if rd.username:
which += rd.username
return load_viewer_profiles(which)
@endpoint('/reader-profiles/save', methods={'POST'}, postprocess=json)
def save_reader_profile(ctx, rd):
try:
data = load_json_file(rd.request_body_file)
name, profile = data['name'], data['profile']
if not isinstance(profile, dict):
raise TypeError('profile must be a dict')
except Exception as err:
raise HTTPBadRequest(f'Invalid query: {err}')
from calibre.gui2.viewer.config import save_viewer_profile
which = 'user:'
if rd.username:
which += rd.username
save_viewer_profile(name, profile, which)
return True
@endpoint('/get/{what}/{book_id}/{library_id=None}', android_workaround=True)
def get(ctx, rd, what, book_id, library_id):
book_id, rest = book_id.partition('_')[::2]

View File

@ -564,6 +564,9 @@ class ProfilesOverlay(PrefsOverlay):
def create_panel_impl(self, container):
return create_profiles_panel(container, self.overlay.hide_current_panel, self.on_change)
def handle_escape(self):
self.overlay.hide_current_panel()
# }}}
class FontSizeOverlay: # {{{

View File

@ -136,6 +136,28 @@ class ReadUI:
error_dialog(_('Could not copy to clipboard'), _('No permission to write to clipboard'))
)
ui_operations.get_all_profiles = def(proceed):
ajax('reader-profiles/get-all', def(end_type, xhr, ev):
if end_type is not 'load':
if end_type is 'abort': return
return self.show_error(_('Failed to load profiles'), _(
'Could not load profiles: with error: {}').format(xhr.error_html))
try:
result = JSON.parse(xhr.responseText)
except Exception:
return self.show_error(_('Failed to parse profiles'), _('Unparseable data received for profiles'))
proceed(result)
).send()
ui_operations.save_profile = def(profile_name, profile, proceed):
ajax_send('reader-profiles/save', {'name': profile_name, 'profile': profile}, def(end_type, xhr, ev):
if end_type is not 'load':
if end_type is 'abort': return
return self.show_error(_('Failed to load profiles'), _(
'Could not load profiles: with error: {}').format(xhr.error_html))
proceed()
)
def on_resize(self):
self.view.on_resize()