diff cagou/core/cagou_main.py @ 322:e2b51663d8b8

core, android: new share widget + added Cagou to "share" menu: - new intent filter to add Cagou to share menu for all media types - minimum Kivy version is now 1.11.0 - new "Share" widget to display data to share via SàT and select the target - new core.platform_ module (the suffix "_" avoid trouble with standard "platform" module), for platform specific code. - Android intent are now checked on startup and "on_new_intent" events - if a android.intent.action.SEND action is received (i.e. some data is shared), the "Share" widget is shown - new Cagou.share method to share data using "Share" widget - new Cagou.getAncestorWidget method to easily retrieve an instance of a specific class in a widget's ancestors - ContactList's Avatar and ContactItem widgets have been moved to core.common
author Goffi <goffi@goffi.org>
date Fri, 06 Dec 2019 13:23:03 +0100
parents 834d5c267219
children 5bd583d00594
line wrap: on
line diff
--- a/cagou/core/cagou_main.py	Fri Dec 06 13:23:03 2019 +0100
+++ b/cagou/core/cagou_main.py	Fri Dec 06 13:23:03 2019 +0100
@@ -1,5 +1,4 @@
-#!/usr//bin/env python2
-# -*- coding: utf-8 -*-
+#!/usr/bin/env python3
 
 # Cagou: desktop/mobile frontend for Salut à Toi XMPP client
 # Copyright (C) 2016-2019 Jérôme Poisson (goffi@goffi.org)
@@ -26,7 +25,6 @@
 kivy_hack.do_hack()
 from .constants import Const as C
 from sat.core import log as logging
-log = logging.getLogger(__name__)
 from sat.core import exceptions
 from sat_frontends.quick_frontend.quick_app import QuickApp
 from sat_frontends.quick_frontend import quick_widgets
@@ -37,7 +35,7 @@
 from sat.tools import config
 from sat.tools.common import dynamic_import
 import kivy
-kivy.require('1.10.0')
+kivy.require('1.11.0')
 import kivy.support
 main_config = config.parseMainConf()
 bridge_name = config.getConfig(main_config, '', 'bridge', 'dbus')
@@ -65,6 +63,7 @@
 from kivy import utils as kivy_utils
 from kivy.config import Config as KivyConfig
 from .cagou_widget import CagouWidget
+from .share_widget import ShareWidget
 from . import widgets_handler
 from .common import IconButton
 from . import menu
@@ -74,6 +73,11 @@
 import cagou
 import cagou.plugins
 import cagou.kv
+
+
+log = logging.getLogger(__name__)
+
+
 try:
     from plyer import notification
 except ImportError:
@@ -85,28 +89,20 @@
 
 if kivy_utils.platform == "android":
     import socket
+    from .platform_ import android
+    android.init_platform()
+else:
+    # we don't want multi-touch emulation with mouse
 
-    # FIXME: move to separate android module
-    # sys.platform is "linux" on android by default
-    # so we change it to allow backend to detect android
-    sys.platform = "android"
-    C.PLUGIN_EXT = 'pyc'
-    SOCKET_DIR = "/data/data/org.salutatoi.cagou/"
-    SOCKET_FILE = ".socket"
-    STATE_RUNNING = b"running"
-    STATE_PAUSED = b"paused"
-    STATE_STOPPED = b"stopped"
+    # this option doesn't make sense on Android and cause troubles, so we only activate
+    # it for other platforms (cf. https://github.com/kivy/kivy/issues/6229)
+    KivyConfig.set('input', 'mouse', 'mouse,disable_multitouch')
 
 
 ## General Configuration ##
 
 # we want white background by default
 Window.clearcolor = (1, 1, 1, 1)
-# we don't want multi-touch emulation with mouse
-if sys.platform != 'android':
-    # this option doesn't make sense on Android and cause troubles
-    # cf. https://github.com/kivy/kivy/issues/6229
-    KivyConfig.set('input', 'mouse', 'mouse,disable_multitouch')
 
 
 class NotifsIcon(IconButton):
@@ -347,21 +343,21 @@
             #      try to call a bridge method in on_pause method, the call data
             #      is not written before the actual pause
             s = self._frontend_status_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-            s.connect(os.path.join(SOCKET_DIR, SOCKET_FILE))
-            s.sendall(STATE_RUNNING)
+            s.connect(os.path.join(android.SOCKET_DIR, android.SOCKET_FILE))
+            s.sendall(android.STATE_RUNNING)
 
     def on_pause(self):
         self.host.sync = False
-        self._frontend_status_socket.sendall(STATE_PAUSED)
+        self._frontend_status_socket.sendall(android.STATE_PAUSED)
         return True
 
     def on_resume(self):
-        self._frontend_status_socket.sendall(STATE_RUNNING)
+        self._frontend_status_socket.sendall(android.STATE_RUNNING)
         self.host.sync = True
 
     def on_stop(self):
         if sys.platform == "android":
-            self._frontend_status_socket.sendall(STATE_STOPPED)
+            self._frontend_status_socket.sendall(android.STATE_STOPPED)
             self._frontend_status_socket.close()
 
     def key_input(self, window, key, scancode, codepoint, modifier):
@@ -371,9 +367,9 @@
         elif key == 292:
             # F11: full screen
             if not Window.fullscreen:
-                window.fullscreen = 'auto'
+                Window.fullscreen = 'auto'
             else:
-                window.fullscreen = False
+                Window.fullscreen = False
             return True
         elif key == 109 and modifier == ['alt']:
             # M-m we hide/show menu
@@ -403,13 +399,6 @@
         if bridge_name == 'embedded':
             from sat.core import sat_main
             self.sat = sat_main.SAT()
-        if sys.platform == 'android':
-            from jnius import autoclass
-            service = autoclass('org.salutatoi.cagou.ServiceBackend')
-            mActivity = autoclass('org.kivy.android.PythonActivity').mActivity
-            argument = ''
-            service.start(mActivity, argument)
-            self.service = service
 
         bridge_module = dynamic_import.bridge(bridge_name, 'sat_frontends.bridge')
         if bridge_module is None:
@@ -458,6 +447,9 @@
             patches.apply()
             log.warning("SSL certificate validation is disabled, this is unsecure!")
 
+        if sys.platform == 'android':
+            android.host_init(self)
+
     @property
     def visible_widgets(self):
         for w_list in self._visible_widgets.values():
@@ -954,6 +946,8 @@
 
     def closeUI(self):
         self.app.root.show()
+        screen = self.app.root._manager.get_screen("extra")
+        screen.clear_widgets()
 
     def getDefaultAvatar(self, entity=None):
         return self.app.default_avatar
@@ -984,6 +978,13 @@
         else:
             log.warning(_("unknown dialog type: {dialog_type}").format(dialog_type=type))
 
+    def share(self, media_type, data):
+        share_wid = ShareWidget(media_type=media_type, data=data)
+        try:
+            self.showExtraUI(share_wid)
+        except Exception as e:
+            log.error(e)
+            self.closeUI()
 
     def desktop_notif(self, message, title='', duration=5000):
         global notification
@@ -998,3 +999,15 @@
                 log.warning(_("Can't use notifications, disabling: {msg}").format(
                     msg = e))
                 notification = None
+
+    def getAncestorWidget(self, wid, cls):
+        """Retrieve an ancestor of given class
+
+        @param wid(Widget): current widget
+        @param cls(type): class of the ancestor to retrieve
+        @return (Widget, None): found instance or None
+        """
+        parent = wid.parent
+        while parent and parent.__class__ != cls:
+            parent = parent.parent
+        return parent