Added multilingual text input options

This commit is contained in:
Mark Qvist 2024-01-05 18:05:34 +01:00
parent 2ef0941a6d
commit b12860f7d7
10 changed files with 287 additions and 18 deletions

View File

@ -10,7 +10,7 @@ source.exclude_patterns = app_storage/*,venv/*,Makefile,./Makefil*,requirements,
version.regex = __version__ = ['"](.*)['"]
version.filename = %(source.dir)s/main.py
android.numeric_version = 20240103
android.numeric_version = 20240105
# Cryptography recipe is currently broken, using RNS-internal crypto for now
requirements = kivy==2.2.1,libbz2,pillow,qrcode==7.3.1,usb4a,usbserial4a

View File

@ -69,8 +69,8 @@ if args.daemon:
colors = DaemonElement; Telemeter = DaemonElement; CustomMapMarker = DaemonElement; MBTilesMapSource = DaemonElement;
MapSource = DaemonElement; webbrowser = DaemonElement; Conversations = DaemonElement; MsgSync = DaemonElement;
NewConv = DaemonElement; Telemetry = DaemonElement; ObjectDetails = DaemonElement; Announces = DaemonElement;
Messages = DaemonElement; ts_format = DaemonElement; messages_screen_kv = DaemonElement; plyer = DaemonElement;
ContentNavigationDrawer = DaemonElement; DrawerList = DaemonElement; IconListItem = DaemonElement;
Messages = DaemonElement; ts_format = DaemonElement; messages_screen_kv = DaemonElement; plyer = DaemonElement; multilingual_markup = DaemonElement;
ContentNavigationDrawer = DaemonElement; DrawerList = DaemonElement; IconListItem = DaemonElement; escape_markup = DaemonElement;
else:
from kivymd.app import MDApp
@ -96,6 +96,7 @@ else:
from mapview import CustomMapMarker
from mapview.mbtsource import MBTilesMapSource
from mapview.source import MapSource
from kivy.utils import escape_markup
import webbrowser
import kivy.core.image
kivy.core.image.Logger = redirect_log()
@ -110,6 +111,7 @@ else:
from ui.announces import Announces
from ui.messages import Messages, ts_format, messages_screen_kv
from ui.helpers import ContentNavigationDrawer, DrawerList, IconListItem
from ui.helpers import multilingual_markup
from jnius import cast
from jnius import autoclass
@ -130,6 +132,7 @@ else:
from .ui.objectdetails import ObjectDetails
from .ui.messages import Messages, ts_format, messages_screen_kv
from .ui.helpers import ContentNavigationDrawer, DrawerList, IconListItem
from .ui.helpers import multilingual_markup
from kivy.config import Config
Config.set('input', 'mouse', 'mouse,disable_multitouch')
@ -180,6 +183,7 @@ class SidebandApp(MDApp):
self.set_ui_theme()
self.font_config()
self.update_input_language()
self.dark_theme_text_color = dark_theme_text_color
self.conversations_view = None
@ -367,7 +371,21 @@ class SidebandApp(MDApp):
LabelBase.register(name="emoji",
fn_regular=fb_path+"NotoEmoji-Regular.ttf")
LabelBase.register(name="combined",
fn_regular=fb_path+"NotoSans-Regular.ttf",
fn_bold=fb_path+"NotoSans-Bold.ttf",
fn_italic=fb_path+"NotoSans-Italic.ttf",
fn_bolditalic=fb_path+"NotoSans-BoldItalic.ttf")
def update_input_language(self):
language = self.sideband.config["input_language"]
if language == None:
self.input_font = "Roboto"
RNS.log("Setting input language to default set", RNS.LOG_DEBUG)
else:
self.input_font = language
RNS.log("Setting input language to "+str(language), RNS.LOG_DEBUG)
def update_ui_colors(self):
if self.sideband.config["dark_ui"]:
@ -1071,7 +1089,8 @@ class SidebandApp(MDApp):
self.messages_view.ids.messages_scrollview.add_widget(list_widget)
self.messages_view.ids.messages_scrollview.scroll_y = 0.0
self.messages_view.ids.messages_toolbar.title = self.sideband.peer_display_name(context_dest)
conv_title = multilingual_markup(escape_markup(str(self.sideband.peer_display_name(context_dest))).encode("utf-8")).decode("utf-8")
self.messages_view.ids.messages_toolbar.title = conv_title
self.messages_view.ids.messages_scrollview.active_conversation = context_dest
self.sideband.setstate("app.active_conversation", context_dest)
@ -1629,6 +1648,8 @@ class SidebandApp(MDApp):
self.settings_screen.ids.settings_scrollview.effect_cls = ScrollEffect
self.settings_screen.ids.settings_info_lang.text = "\nIf you write messages in another script than Latin, Greek or Cyrillic, you can configure the text input language for messages and other fields below.\n"
info1_text = "\nYou can set your [b]Display Name[/b] to a custom value, or leave it as the default unspecified value. "
info1_text += "This name will be included in any announces you send, and will be visible to others on the network. "
info1_text += "\n\nYou can manually specify which [b]Propagation Node[/b] to use, but if none is specified, Sideband will "
@ -1676,6 +1697,54 @@ class SidebandApp(MDApp):
self.sideband.config["lxmf_propagation_node"] = new_addr
self.sideband.set_active_propagation_node(self.sideband.config["lxmf_propagation_node"])
def save_input_lang(sender=None, event=None):
if sender.active:
if sender != self.settings_screen.ids.settings_lang_default:
self.settings_screen.ids.settings_lang_default.active = False
if sender != self.settings_screen.ids.settings_lang_chinese:
self.settings_screen.ids.settings_lang_chinese.active = False
if sender != self.settings_screen.ids.settings_lang_japanese:
self.settings_screen.ids.settings_lang_japanese.active = False
if sender != self.settings_screen.ids.settings_lang_korean:
self.settings_screen.ids.settings_lang_korean.active = False
if sender != self.settings_screen.ids.settings_lang_devangari:
self.settings_screen.ids.settings_lang_devangari.active = False
if sender != self.settings_screen.ids.settings_lang_hebrew:
self.settings_screen.ids.settings_lang_hebrew.active = False
RNS.log("Sender: "+str(sender))
if self.settings_screen.ids.settings_lang_default.active:
self.sideband.config["input_language"] = None
self.settings_screen.ids.settings_display_name.font_name = ""
elif self.settings_screen.ids.settings_lang_chinese.active:
self.sideband.config["input_language"] = "chinese"
self.settings_screen.ids.settings_display_name.font_name = "chinese"
elif self.settings_screen.ids.settings_lang_japanese.active:
self.sideband.config["input_language"] = "japanese"
self.settings_screen.ids.settings_display_name.font_name = "japanese"
elif self.settings_screen.ids.settings_lang_korean.active:
self.sideband.config["input_language"] = "korean"
self.settings_screen.ids.settings_display_name.font_name = "korean"
elif self.settings_screen.ids.settings_lang_devangari.active:
self.sideband.config["input_language"] = "combined"
self.settings_screen.ids.settings_display_name.font_name = "combined"
elif self.settings_screen.ids.settings_lang_hebrew.active:
self.sideband.config["input_language"] = "hebrew"
self.settings_screen.ids.settings_display_name.font_name = "hebrew"
else:
self.sideband.config["input_language"] = None
self.settings_screen.ids.settings_display_name.font_name = ""
self.sideband.save_configuration()
self.update_input_language()
def save_dark_ui(sender=None, event=None):
self.sideband.config["dark_ui"] = self.settings_screen.ids.settings_dark_ui.active
self.sideband.save_configuration()
@ -1840,6 +1909,39 @@ class SidebandApp(MDApp):
self.settings_screen.ids.settings_debug.active = self.sideband.config["debug"]
self.settings_screen.ids.settings_debug.bind(active=save_debug)
self.settings_screen.ids.settings_lang_default.active = False
self.settings_screen.ids.settings_lang_chinese.active = False
self.settings_screen.ids.settings_lang_japanese.active = False
self.settings_screen.ids.settings_lang_korean.active = False
self.settings_screen.ids.settings_lang_devangari.active = False
self.settings_screen.ids.settings_lang_default.bind(active=save_input_lang)
self.settings_screen.ids.settings_lang_chinese.bind(active=save_input_lang)
self.settings_screen.ids.settings_lang_japanese.bind(active=save_input_lang)
self.settings_screen.ids.settings_lang_korean.bind(active=save_input_lang)
self.settings_screen.ids.settings_lang_devangari.bind(active=save_input_lang)
self.settings_screen.ids.settings_lang_hebrew.bind(active=save_input_lang)
input_lang = self.sideband.config["input_language"]
if input_lang == None:
self.settings_screen.ids.settings_lang_default.active = True
self.settings_screen.ids.settings_display_name.font_name = ""
elif input_lang == "chinese":
self.settings_screen.ids.settings_lang_chinese.active = True
self.settings_screen.ids.settings_display_name.font_name = "chinese"
elif input_lang == "japanese":
self.settings_screen.ids.settings_lang_japanese.active = True
self.settings_screen.ids.settings_display_name.font_name = "japanese"
elif input_lang == "korean":
self.settings_screen.ids.settings_lang_korean.active = True
self.settings_screen.ids.settings_display_name.font_name = "korean"
elif input_lang == "devangari":
self.settings_screen.ids.settings_lang_devangari.active = True
self.settings_screen.ids.settings_display_name.font_name = "combined"
elif input_lang == "hebrew":
self.settings_screen.ids.settings_lang_hebrew.active = True
self.settings_screen.ids.settings_display_name.font_name = "hebrew"
else:
self.settings_screen.ids.settings_display_name.font_name = ""
self.settings_ready = True
def close_settings_action(self, sender=None):

View File

@ -414,6 +414,11 @@ class SidebandCore():
if not "display_style_in_contact_list" in self.config:
self.config["display_style_in_contact_list"] = False
if not "input_language" in self.config:
self.config["input_language"] = None
if not "allow_predictive_text" in self.config:
self.config["allow_predictive_text"] = False
if not "connect_transport" in self.config:
self.config["connect_transport"] = False
if not "connect_rnode" in self.config:

View File

@ -16,6 +16,12 @@ from kivymd.uix.dialog import MDDialog
from kivy.lang.builder import Builder
from kivy.utils import escape_markup
if RNS.vendor.platformutils.get_platform() == "android":
from ui.helpers import multilingual_markup
else:
from .helpers import multilingual_markup
if RNS.vendor.platformutils.get_platform() == "android":
from ui.helpers import ts_format
else:
@ -93,9 +99,9 @@ class Announces():
trust_icon = "account-question"
def gen_info(ts, dest, name, dtype):
name = multilingual_markup(escape_markup(str(name)).encode("utf-8")).decode("utf-8")
def x(sender):
yes_button = MDRectangleFlatButton(text="OK",font_size=dp(18))
yes_button = MDRectangleFlatButton(text="OK",font_size=dp(18))
if dtype == "lxmf.delivery":
ad_text = "[size=22dp]LXMF Peer[/size]\n\nReceived: "+ts+"\nAnnounced Name: "+name+"\nAddress: "+RNS.prettyhexrep(dest)
@ -118,7 +124,7 @@ class Announces():
time_string = time.strftime(ts_format, time.localtime(ts))
if dest_type == "lxmf.delivery":
disp_name = self.app.sideband.peer_display_name(context_dest)
disp_name = multilingual_markup(escape_markup(str(self.app.sideband.peer_display_name(context_dest))).encode("utf-8")).decode("utf-8")
iconl = IconLeftWidget(icon=trust_icon)
elif dest_type == "lxmf.propagation":

View File

@ -17,6 +17,12 @@ from kivymd.uix.dialog import MDDialog
from kivy.lang.builder import Builder
from kivy.utils import escape_markup
if RNS.vendor.platformutils.get_platform() == "android":
from ui.helpers import multilingual_markup
else:
from .helpers import multilingual_markup
class NewConv(BoxLayout):
pass
@ -162,9 +168,10 @@ class Conversations():
unread = conv["unread"]
last_activity = conv["last_activity"]
peer_disp_name = multilingual_markup(escape_markup(str(self.app.sideband.peer_display_name(context_dest))).encode("utf-8")).decode("utf-8")
if not context_dest in self.added_item_dests:
iconl = self.get_icon(conv)
item = OneLineAvatarIconListItem(text=self.app.sideband.peer_display_name(context_dest), on_release=self.app.conversation_action)
item = OneLineAvatarIconListItem(text=peer_disp_name, on_release=self.app.conversation_action)
item.add_widget(iconl)
item.last_activity = last_activity
item.iconl = iconl
@ -185,6 +192,11 @@ class Conversations():
yes_button = MDRectangleFlatButton(text="Save",font_size=dp(18), theme_text_color="Custom", line_color=self.app.color_accept, text_color=self.app.color_accept)
no_button = MDRectangleFlatButton(text="Cancel",font_size=dp(18))
dialog_content = ConvSettings(disp_name=disp_name, context_dest=RNS.hexrep(dest, delimit=False), trusted=is_trusted, telemetry=send_telemetry, allow_requests=allow_requests)
if self.app.sideband.config["input_language"] != None:
dialog_content.ids.name_field.font_name = self.app.sideband.config["input_language"]
else:
dialog_content.ids.name_field.font_name = ""
dialog = MDDialog(
title="Edit Conversation",
text= "With "+RNS.prettyhexrep(dest),
@ -388,7 +400,6 @@ class Conversations():
else:
for w in self.list.children:
if w.sb_uid == context_dest:
disp_name = self.app.sideband.peer_display_name(context_dest)
trust_icon = self.trust_icon(conv)
trusted = conv["trust"] == 1
da = self.app.sideband.DEFAULT_APPEARANCE
@ -410,7 +421,7 @@ class Conversations():
if w.iconl.icon != trust_icon: w.iconl.icon = trust_icon
if w.sb_unread != unread: w.sb_unread = unread
if w.text != disp_name: w.text = disp_name
if w.text != peer_disp_name: w.text = peer_disp_name
self.list.children.sort(key=lambda w: (w.trusted, w.last_activity))

File diff suppressed because one or more lines are too long

View File

@ -1438,8 +1438,8 @@ MDScreen:
MDBoxLayout:
orientation: "horizontal"
size_hint_y: None
padding: [0,0,dp(24),dp(0)]
height: dp(48)
padding: [0,0,dp(24),dp(24)]
height: dp(48+24)
MDLabel:
text: "Debug Logging"
@ -1450,6 +1450,141 @@ MDScreen:
pos_hint: {"center_y": 0.3}
disabled: False
active: False
MDLabel:
text: "Input Options & Localisation"
font_style: "H6"
size_hint_y: None
height: self.texture_size[1]
MDLabel:
id: settings_info_lang
markup: True
text: ""
size_hint_y: None
height: self.texture_size[1]
MDBoxLayout:
orientation: "horizontal"
size_hint_y: None
padding: [0,0,dp(24),dp(0)]
height: dp(48)
MDLabel:
text: "Latin, Greek, Cyrillic"
font_style: "H6"
MDSwitch:
id: settings_lang_default
pos_hint: {"center_y": 0.3}
active: False
MDBoxLayout:
orientation: "horizontal"
size_hint_y: None
padding: [0,0,dp(24),dp(0)]
height: dp(48)
MDLabel:
text: "Chinese"
font_style: "H6"
MDSwitch:
id: settings_lang_chinese
pos_hint: {"center_y": 0.3}
active: False
MDBoxLayout:
orientation: "horizontal"
size_hint_y: None
padding: [0,0,dp(24),dp(0)]
height: dp(48)
MDLabel:
text: "Japanese"
font_style: "H6"
MDSwitch:
id: settings_lang_japanese
pos_hint: {"center_y": 0.3}
active: False
MDBoxLayout:
orientation: "horizontal"
size_hint_y: None
padding: [0,0,dp(24),dp(0)]
height: dp(48)
MDLabel:
text: "Korean"
font_style: "H6"
MDSwitch:
id: settings_lang_korean
pos_hint: {"center_y": 0.3}
active: False
MDBoxLayout:
orientation: "horizontal"
size_hint_y: None
padding: [0,0,dp(24),dp(0)]
height: dp(48)
MDLabel:
text: "Devangari"
font_style: "H6"
MDSwitch:
id: settings_lang_devangari
pos_hint: {"center_y": 0.3}
active: False
MDBoxLayout:
orientation: "horizontal"
size_hint_y: None
padding: [0,0,dp(24),dp(0)]
height: dp(48)
MDLabel:
text: "Hebrew (incomplete)"
font_style: "H6"
MDSwitch:
id: settings_lang_hebrew
pos_hint: {"center_y": 0.3}
active: False
# MDBoxLayout:
# orientation: "horizontal"
# size_hint_y: None
# padding: [0,0,dp(24),dp(0)]
# height: dp(48)
# MDLabel:
# text: "Allow Predictive Text"
# font_style: "H6"
# MDSwitch:
# id: settings_allow_predictive_text
# pos_hint: {"center_y": 0.3}
# active: False
# MDBoxLayout:
# orientation: "vertical"
# size_hint_y: None
# height: self.minimum_height
# padding: [0, dp(24), 0, dp(24)]
# MDRectangleFlatIconButton:
# id: hardware_rnode_button
# icon: "translate"
# text: "Input Languages"
# padding: [dp(0), dp(14), dp(0), dp(14)]
# icon_size: dp(24)
# font_size: dp(16)
# size_hint: [1.0, None]
# on_release: root.app.input_languages_action(self)
"""
layout_repository_screen = """

View File

@ -176,6 +176,8 @@ class Messages():
intensity_msgs = intensity_msgs_light
mt_color = [1.0, 1.0, 1.0, 0.95]
self.ids.message_text.font_name = self.app.input_font
if self.loading_earlier_messages:
self.new_messages.reverse()

View File

@ -20,6 +20,11 @@ from kivymd.toast import toast
from datetime import datetime
from kivy.utils import escape_markup
if RNS.vendor.platformutils.get_platform() == "android":
from ui.helpers import multilingual_markup
else:
from .helpers import multilingual_markup
if RNS.vendor.platformutils.get_platform() == "android":
from ui.helpers import ts_format
@ -138,7 +143,7 @@ class ObjectDetails():
self.coords = None
self.telemetry_list.data = []
pds = self.app.sideband.peer_display_name(source_dest)
pds = multilingual_markup(escape_markup(str(self.app.sideband.peer_display_name(source_dest))).encode("utf-8")).decode("utf-8")
appearance = self.app.sideband.peer_appearance(source_dest)
self.screen.ids.name_label.text = pds
@ -330,7 +335,7 @@ class RVDetails(MDRecycleView):
Clipboard.copy(istr)
toast("Copied to clipboard")
release_function = copy_info
external_text = escape_markup(istr)
external_text = multilingual_markup(escape_markup(istr).encode("utf-8")).decode("utf-8")
formatted_values = f"[b]Information[/b]: {external_text}"
elif name == "Received":
formatted_values = ""

View File

@ -15,11 +15,8 @@ from kivy.effects.scroll import ScrollEffect
from kivy.clock import Clock
from sideband.sense import Telemeter
import threading
from datetime import datetime
if RNS.vendor.platformutils.get_platform() == "android":
from ui.helpers import ts_format
from android.permissions import request_permissions, check_permission
@ -374,6 +371,11 @@ class Telemetry():
self.sensors_screen.ids.telemetry_s_information_text.text = str(self.app.sideband.config["telemetry_s_information_text"])
self.sensors_screen.ids.telemetry_s_information_text.bind(focus=self.sensors_save)
if self.app.sideband.config["input_language"] != None:
self.sensors_screen.ids.telemetry_s_information_text.font_name = self.app.sideband.config["input_language"]
else:
self.sensors_screen.ids.telemetry_s_information_text.font_name = ""
def sensors_open(self, sender=None, direction="left", no_transition=False):
if no_transition:
self.app.root.ids.screen_manager.transition = self.app.no_transition