Merge branch 'dev' into 'main'
Merging dev into main See merge request mx-moment/moment!19
This commit is contained in:
		| @@ -507,33 +507,6 @@ class Backend: | ||||
|                     ping=sum(times) // len(times), status=PingStatus.Done, | ||||
|                 ) | ||||
|  | ||||
|  | ||||
|     def _get_homeserver_stability( | ||||
|         self, logs: List[Dict[str, Any]], | ||||
|     ) -> Tuple[float, List[timedelta]]: | ||||
|         """Return server stability % and a list of downtime durations.""" | ||||
|  | ||||
|         stability = 100.0 | ||||
|         durations = [] | ||||
|  | ||||
|         for period in logs: | ||||
|             started_at     = datetime.fromtimestamp(period["datetime"]) | ||||
|             time_since_now = datetime.now() - started_at | ||||
|  | ||||
|             if time_since_now.days > 30 or period["type"] != 1:  # 1 = downtime | ||||
|                 continue | ||||
|  | ||||
|             lasted_minutes  = period["duration"] / 60 | ||||
|             durations.append(timedelta(seconds=period["duration"])) | ||||
|  | ||||
|             stability -= ( | ||||
|                 (lasted_minutes * stability / 1000) / | ||||
|                 max(1, time_since_now.days / 3) | ||||
|             ) | ||||
|  | ||||
|         return (stability, durations) | ||||
|  | ||||
|  | ||||
|     async def fetch_homeservers(self) -> None: | ||||
|         """Retrieve a list of public homeservers and add them to our model.""" | ||||
|  | ||||
| @@ -557,7 +530,7 @@ class Backend: | ||||
|             connector        = session.connector, | ||||
|         ) | ||||
|  | ||||
|         api_list = "https://publiclist.anchel.nl/publiclist.json" | ||||
|         api_list = "https://joinmatrix.org/servers.json" | ||||
|         try: | ||||
|             response = await session.get(api_list) | ||||
|         except: | ||||
| @@ -568,27 +541,19 @@ class Backend: | ||||
|         coros    = [] | ||||
|  | ||||
|         for server in (await response.json()): | ||||
|             homeserver_url = server["homeserver"] | ||||
|             homeserver_url = "https://" + server["domain"] | ||||
|  | ||||
|             if homeserver_url.startswith("http://"):  # insecure server | ||||
|             if not server["open"]: # ignore closed servers | ||||
|                 continue | ||||
|  | ||||
|             if not re.match(r"^https?://.+", homeserver_url): | ||||
|                 homeserver_url = f"https://{homeserver_url}" | ||||
|  | ||||
|             if server["country"] == "USA": | ||||
|                 server["country"] = "United States" | ||||
|  | ||||
|             stability, durations = \ | ||||
|                 self._get_homeserver_stability(server["monitor"]["logs"]) | ||||
|  | ||||
|             self.models["homeservers"][homeserver_url] = Homeserver( | ||||
|                 id           = homeserver_url, | ||||
|                 name         = server["name"], | ||||
|                 site_url     = server["url"], | ||||
|                 country      = server["country"], | ||||
|                 stability    = stability, | ||||
|                 downtimes_ms = [d.total_seconds() * 1000 for d in durations], | ||||
|                 site_url     = server["domain"], | ||||
|                 country      = server["jurisdiction"], | ||||
|                 stability    = 0, | ||||
|                 downtimes_ms = 0, | ||||
|                 # austin's list doesn't have stability/downtime | ||||
|             ) | ||||
|  | ||||
|             coros.append(self._ping_homeserver(session, homeserver_url)) | ||||
|   | ||||
| @@ -1,59 +0,0 @@ | ||||
| // Copyright Mirage authors & contributors <https://github.com/mirukana/mirage> | ||||
| // and Moment contributors <https://gitlab.com/mx-moment/moment> | ||||
| // SPDX-License-Identifier: LGPL-3.0-or-later | ||||
|  | ||||
| pragma Singleton | ||||
| import QtQuick 2.12 | ||||
|  | ||||
| QtObject { | ||||
|  | ||||
|     property bool startInTray: false | ||||
|     property string loadQml: "" | ||||
|  | ||||
|     readonly property string help: `Usage: ${Qt.application.name} [options] | ||||
|  | ||||
|     Options: | ||||
|         -t, --start-in-tray  Start in the system tray, without a visible window | ||||
|         -l, --load-qml PATH  Override the file to be loaded as src/gui/UI.qml | ||||
|         -V, --version        Show the application's version and exit | ||||
|         -h, --help           Show this help and exit | ||||
|  | ||||
|     Environment variables: | ||||
|         MOMENT_CONFIG_DIR  Override the default configuration folder | ||||
|         MOMENT_DATA_DIR    Override the default application data folder | ||||
|         MOMENT_CACHE_DIR   Override the default cache and downloads folder | ||||
|         http_proxy         Override the General.proxy setting, see settings.py | ||||
|     ` | ||||
|  | ||||
|     readonly property bool ready: { | ||||
|         const passedArguments = Qt.application.arguments.slice(1) | ||||
|  | ||||
|         while (passedArguments.length) { | ||||
|             switch (passedArguments.shift()) { | ||||
|                 case "-h": | ||||
|                 case "--help": | ||||
|                     print("\n\n" + help.replace(/^ {4}/gm, "")) | ||||
|                     Qt.quit() | ||||
|                     break | ||||
|  | ||||
|                 case "-v": | ||||
|                 case "--version": | ||||
|                     print(Qt.application.version) | ||||
|                     Qt.quit() | ||||
|                     break | ||||
|  | ||||
|                 case "-t": | ||||
|                 case "--start-in-tray": | ||||
|                     startInTray = true | ||||
|                     break | ||||
|  | ||||
|                 case "-l": | ||||
|                 case "--load-qml": | ||||
|                     loadQml = passedArguments.shift() | ||||
|                     break | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return true | ||||
|     } | ||||
| } | ||||
| @@ -115,7 +115,6 @@ HBox { | ||||
|                 model: [ | ||||
|                     qsTr("Ping"), | ||||
|                     qsTr("Name & location"), | ||||
|                     qsTr("Stability"), | ||||
|                     qsTr("Site"), | ||||
|                 ] | ||||
|  | ||||
|   | ||||
| @@ -66,44 +66,10 @@ HTile { | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         TitleRightInfoLabel { | ||||
|             tile: root | ||||
|             font.pixelSize: theme.fontSize.normal | ||||
|  | ||||
|             text: | ||||
|                 model.stability === -1 ? | ||||
|                 "" : | ||||
|                 qsTr("%1%").arg(Math.max(0, parseInt(model.stability, 10))) | ||||
|  | ||||
|             color: | ||||
|                 model.stability >= 95 ? theme.colors.positiveText : | ||||
|                 model.stability >= 85 ? theme.colors.warningText : | ||||
|                 theme.colors.errorText | ||||
|  | ||||
|             HoverHandler { id: rightInfoHover } | ||||
|  | ||||
|             HToolTip { | ||||
|                 readonly property var times: JSON.parse(model.downtimes_ms) | ||||
|                 readonly property real total: utils.sum(times) | ||||
|  | ||||
|                 visible: model.stability !== -1 && rightInfoHover.hovered | ||||
|                 text: | ||||
|                     total === 0 ? | ||||
|                     qsTr("No downtimes in the last 30 days") : | ||||
|                     qsTr( | ||||
|                         "Last 30 days downtimes: %1, average: %2, " + | ||||
|                         "longest: %3, total: %4" | ||||
|                     ).arg(times.length) | ||||
|                      .arg(utils.formatRelativeTime(total / times.length)) | ||||
|                      .arg(utils.formatRelativeTime(Math.max.apply(Math,times))) | ||||
|                      .arg(utils.formatRelativeTime(total)) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         HButton { | ||||
|             icon.name: "server-visit-website" | ||||
|             backgroundColor: "transparent" | ||||
|             onClicked: Qt.openUrlExternally(model.site_url) | ||||
|             onClicked: Qt.openUrlExternally("https://"+model.site_url) | ||||
|  | ||||
|             Layout.fillHeight: true | ||||
|         } | ||||
|   | ||||
| @@ -28,6 +28,8 @@ ApplicationWindow { | ||||
|     property var theme: null | ||||
|     property var themeRules: null | ||||
|     property string settingsFolder | ||||
|     property bool startInTray | ||||
|     property string loadQml | ||||
|  | ||||
|     readonly property var visibleMenus: ({}) | ||||
|     readonly property var visiblePopups: ({}) | ||||
| @@ -98,7 +100,7 @@ ApplicationWindow { | ||||
|     minimumHeight: theme ? theme.minimumSupportedHeight : 120 | ||||
|     width: Math.min(screen.width, 1152) | ||||
|     height: Math.min(screen.height, 768) | ||||
|     visible: ArgumentParser.ready && ! ArgumentParser.startInTray | ||||
|     visible: ! startInTray | ||||
|     color: "transparent" | ||||
|  | ||||
|     onClosing: if (py.ready && settings.General.close_to_tray) { | ||||
| @@ -123,8 +125,8 @@ ApplicationWindow { | ||||
|         focus: true | ||||
|         scale: py.ready ? 1 : 0.5 | ||||
|         source: | ||||
|             ArgumentParser.ready && py.ready ? | ||||
|             (ArgumentParser.loadQml || "UI.qml") : | ||||
|             py.ready ? | ||||
|             (loadQml || "UI.qml") : | ||||
|             "" | ||||
|  | ||||
|         Behavior on scale { HNumberAnimation { overshoot: 3; factor: 1.2 } } | ||||
|   | ||||
| @@ -1,2 +1 @@ | ||||
| singleton ModelStore 0.1 ModelStore.qml | ||||
| singleton ArgumentParser 0.1 ArgumentParser.qml | ||||
|   | ||||
							
								
								
									
										39
									
								
								src/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								src/main.cpp
									
									
									
									
									
								
							| @@ -19,6 +19,8 @@ | ||||
| #include <QFile> | ||||
| #include <QLockFile> | ||||
| #include <QMessageBox> | ||||
| #include <QCommandLineParser> | ||||
| #include <iostream> | ||||
| #include <signal.h> | ||||
|  | ||||
| #ifdef Q_OS_UNIX | ||||
| @@ -372,6 +374,38 @@ int main(int argc, char *argv[]) { | ||||
|     // because migrate displays a popup dialog | ||||
|     QApplication app(argc, argv); | ||||
|  | ||||
|     QCommandLineParser args; | ||||
|  | ||||
|     QCommandLineOption startInTrayOption(QStringList() << "t" << "start-in-tray", | ||||
|             "Start in the system tray, without a visible window."); | ||||
|     args.addOption(startInTrayOption); | ||||
|  | ||||
|     QCommandLineOption loadQmlOption(QStringList() << "l" << "load-qml", | ||||
|             "Override the file to be loaded as src/gui/UI.qml", "PATH"); | ||||
|     args.addOption(loadQmlOption); | ||||
|  | ||||
|     QCommandLineOption helpOption(QStringList() << "h" << "help", | ||||
|             "Displays help on commandline options."); | ||||
|     args.addOption(helpOption); | ||||
|  | ||||
|     args.addVersionOption(); | ||||
|  | ||||
|     args.process(app); | ||||
|  | ||||
|     if (args.isSet(helpOption)) { | ||||
|         std::cout << args.helpText().toStdString() << std::endl | ||||
|             << "Environment variables:" << std::endl | ||||
|             << "  MOMENT_CONFIG_DIR  Override the configuration folder" | ||||
|             << std::endl | ||||
|             << "  MOMENT_DATA_DIR    Override the application data folder" | ||||
|             << std::endl | ||||
|             << "  MOMENT_CACHE_DIR   Override the cache and downloads folder" | ||||
|             << std::endl | ||||
|             << "  http_proxy         Override the General.proxy setting, see " | ||||
|             << "settings.py" << std::endl; | ||||
|         exit(EXIT_SUCCESS); | ||||
|     } | ||||
|  | ||||
|     if (shouldMigrateFromMirage()) tryMigrateFromMirage(); | ||||
|  | ||||
|     QString customConfigDir(qEnvironmentVariable("MOMENT_CONFIG_DIR")); | ||||
| @@ -489,7 +523,10 @@ int main(int argc, char *argv[]) { | ||||
|         app.exit(EXIT_FAILURE); | ||||
|     } | ||||
|  | ||||
|     component.create(objectContext)->setProperty("settingsFolder", settingsFolder); | ||||
|     QObject *comp = component.create(objectContext); | ||||
|     comp->setProperty("settingsFolder", "file://"+settingsFolder); | ||||
|     comp->setProperty("startInTray",    args.isSet(startInTrayOption)); | ||||
|     comp->setProperty("loadQml",        args.value(loadQmlOption)); | ||||
|  | ||||
|     // Finally, execute the app. Return its exit code after clearing the lock. | ||||
|     int exit_code = app.exec(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	