Compare commits
8 Commits
wip/jimmac
...
gbsneto/au
Author | SHA1 | Date | |
---|---|---|---|
![]() |
47a2e58d45 | ||
![]() |
20d73be57d | ||
![]() |
62233a4db4 | ||
![]() |
4a7e2ddff5 | ||
![]() |
fb737ebde0 | ||
![]() |
bf77cb44e7 | ||
![]() |
c72e2bb4a9 | ||
![]() |
68c182b1df |
@@ -1,6 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/org/gnome/shell/theme">
|
||||
<file>automatic-updates-off-symbolic.svg</file>
|
||||
<file>automatic-updates-on-symbolic.svg</file>
|
||||
<file>automatic-updates-scheduled-symbolic.svg</file>
|
||||
<file>calendar-today.svg</file>
|
||||
<file>checkbox-focused.svg</file>
|
||||
<file>checkbox-off-focused.svg</file>
|
||||
|
1
data/theme/automatic-updates-off-symbolic.svg
Normal file
1
data/theme/automatic-updates-off-symbolic.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><title>EOS_symbolic-icons_v0.1auto-updates_OFF</title><path d="M11.03,10.074a.125.125,0,0,0-.086.213l1.347,1.35a5.733,5.733,0,0,1-4.238,1.9,5.6,5.6,0,0,1-2.282-.484l-1.11,1.11a7.024,7.024,0,0,0,3.392.875,7.3,7.3,0,0,0,5.3-2.339l1.357,1.36a.125.125,0,0,0,.213-.086L15,10Z" style="fill:#999"/><path d="M12.921,5.9a6.354,6.354,0,0,1,.326,1.863.248.248,0,0,0,.244.244h1a.261.261,0,0,0,.257-.265,7.543,7.543,0,0,0-.677-2.991Z" style="fill:#999"/><path d="M6.286,9.707a.994.994,0,0,0,.715.3H9a1,1,0,0,0,1-1v-2A.994.994,0,0,0,9.7,6.3l2.175-2.175,0,0L12.93,3.067l0,0,1.4-1.4a.25.25,0,0,0,0-.354L13.617.608a.25.25,0,0,0-.354,0L11.772,2.1A6.97,6.97,0,0,0,7.948.961,7.3,7.3,0,0,0,2.651,3.3L1.293,1.94a.125.125,0,0,0-.214.086L1,6l3.971-.074a.125.125,0,0,0,.086-.213L3.71,4.363a5.733,5.733,0,0,1,4.238-1.9,5.523,5.523,0,0,1,2.723.739L7.86,6.011H7a1,1,0,0,0-1,1V7.87L3.291,10.58a6,6,0,0,1-.537-2.346.248.248,0,0,0-.244-.245h-1a.261.261,0,0,0-.257.265A7.329,7.329,0,0,0,2.172,11.7L.608,13.263a.25.25,0,0,0,0,.354l.707.707a.25.25,0,0,0,.354,0l1.4-1.4,0,0,1.056-1.056,0,0Z" style="fill:#999"/></svg>
|
After Width: | Height: | Size: 1.1 KiB |
1
data/theme/automatic-updates-on-symbolic.svg
Normal file
1
data/theme/automatic-updates-on-symbolic.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><title>EOS_symbolic-icons_v0.1auto-updates_ON</title><rect x="6.001" y="6.011" width="4" height="4" rx="1" ry="1" style="fill:#999"/><path d="M5.057,5.713,3.71,4.362a5.733,5.733,0,0,1,4.238-1.9,5.173,5.173,0,0,1,5.3,5.305.248.248,0,0,0,.244.244h1a.261.261,0,0,0,.257-.265A6.684,6.684,0,0,0,7.948.961,7.3,7.3,0,0,0,2.65,3.3L1.293,1.94a.125.125,0,0,0-.213.086L1,6l3.971-.074A.125.125,0,0,0,5.057,5.713Z" style="fill:#999"/><path d="M11.03,10.074a.125.125,0,0,0-.086.213l1.347,1.35a5.733,5.733,0,0,1-4.238,1.9,5.173,5.173,0,0,1-5.3-5.305.248.248,0,0,0-.244-.245h-1a.261.261,0,0,0-.257.265,6.684,6.684,0,0,0,6.8,6.785,7.3,7.3,0,0,0,5.3-2.339l1.357,1.36a.125.125,0,0,0,.214-.086L15,10Z" style="fill:#999"/></svg>
|
After Width: | Height: | Size: 767 B |
1
data/theme/automatic-updates-scheduled-symbolic.svg
Normal file
1
data/theme/automatic-updates-scheduled-symbolic.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><title>EOS_symbolic-icons_v0.1update-scheduled_OUTLINE</title><path d="M7.99,15.054A6.7,6.7,0,0,1,1.06,8,6.7,6.7,0,0,1,7.99.954,6.71,6.71,0,0,1,14.948,8,6.71,6.71,0,0,1,7.99,15.054Zm0-12.6A5.2,5.2,0,0,0,2.56,8a5.2,5.2,0,0,0,5.43,5.55A5.215,5.215,0,0,0,13.448,8,5.216,5.216,0,0,0,7.99,2.454Z" style="fill:#999"/><path d="M9.209,10.443,7.2,8.437a.25.25,0,0,1-.073-.177l0-4.01A.25.25,0,0,1,7.379,4h1.25a.25.25,0,0,1,.25.25l0,3.283a.25.25,0,0,0,.073.177l1.5,1.494a.25.25,0,0,1,0,.354l-.883.884A.25.25,0,0,1,9.209,10.443Z" style="fill:#999"/></svg>
|
After Width: | Height: | Size: 603 B |
@@ -9,6 +9,7 @@
|
||||
<file>gdm/realmd.js</file>
|
||||
<file>gdm/util.js</file>
|
||||
|
||||
<file>misc/updateManager.js</file>
|
||||
<file>misc/config.js</file>
|
||||
<file>misc/extensionUtils.js</file>
|
||||
<file>misc/fileUtils.js</file>
|
||||
@@ -116,9 +117,11 @@
|
||||
<file>ui/components/networkAgent.js</file>
|
||||
<file>ui/components/polkitAgent.js</file>
|
||||
<file>ui/components/telepathyClient.js</file>
|
||||
<file>ui/components/updates.js</file>
|
||||
<file>ui/components/keyring.js</file>
|
||||
|
||||
<file>ui/status/accessibility.js</file>
|
||||
<file>ui/status/automaticUpdates.js</file>
|
||||
<file>ui/status/brightness.js</file>
|
||||
<file>ui/status/location.js</file>
|
||||
<file>ui/status/keyboard.js</file>
|
||||
|
338
js/misc/updateManager.js
Normal file
338
js/misc/updateManager.js
Normal file
@@ -0,0 +1,338 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
//
|
||||
// Copyright (C) 2019 Endless Mobile, Inc.
|
||||
//
|
||||
// This is a GNOME Shell component to wrap the interactions over
|
||||
// D-Bus with the Mogwai system daemon.
|
||||
//
|
||||
// Licensed under the GNU General Public License Version 2
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
const { Clutter, Gio, GLib,
|
||||
GObject, Gtk, NM, Shell, St } = imports.gi;
|
||||
|
||||
const NM_SETTING_AUTOMATIC_UPDATES_NOTIFICATION_TIME = "connection.automatic-updates-notification-time";
|
||||
const NM_SETTING_ALLOW_DOWNLOADS = 'connection.allow-downloads';
|
||||
const NM_SETTING_TARIFF_ENABLED = "connection.tariff-enabled";
|
||||
|
||||
const SchedulerInterface = '\
|
||||
<node> \
|
||||
<interface name="com.endlessm.DownloadManager1.Scheduler"> \
|
||||
<property name="ActiveEntryCount" type="u" access="read" /> \
|
||||
<property name="EntryCount" type="u" access="read" /> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const SchedulerProxy = Gio.DBusProxy.makeProxyWrapper(SchedulerInterface);
|
||||
|
||||
let _updateManager = null;
|
||||
|
||||
function getUpdateManager() {
|
||||
if (_updateManager == null)
|
||||
_updateManager = new UpdateManager();
|
||||
return _updateManager;
|
||||
}
|
||||
|
||||
var State = {
|
||||
UNKNOWN: 0,
|
||||
DISCONNECTED: 1,
|
||||
DISABLED: 2,
|
||||
IDLE: 3,
|
||||
SCHEDULED: 4,
|
||||
DOWNLOADING: 5
|
||||
};
|
||||
|
||||
function stateToIconName(state) {
|
||||
switch (state) {
|
||||
case State.UNKNOWN:
|
||||
case State.DISCONNECTED:
|
||||
return null;
|
||||
|
||||
case State.DISABLED:
|
||||
return 'resource:///org/gnome/shell/theme/automatic-updates-off-symbolic.svg';
|
||||
|
||||
case State.IDLE:
|
||||
case State.DOWNLOADING:
|
||||
return 'resource:///org/gnome/shell/theme/automatic-updates-on-symbolic.svg';
|
||||
|
||||
case State.SCHEDULED:
|
||||
return 'resource:///org/gnome/shell/theme/automatic-updates-scheduled-symbolic.svg';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
var UpdateManager = GObject.registerClass ({
|
||||
Properties: {
|
||||
'last-notification-time': GObject.ParamSpec.int('last-notification-time',
|
||||
'last-notification-time',
|
||||
'last-notification-time',
|
||||
GObject.ParamFlags.READWRITE,
|
||||
null),
|
||||
'icon': GObject.ParamSpec.object('icon', 'icon', 'icon',
|
||||
GObject.ParamFlags.READABLE,
|
||||
Gio.Icon.$gtype),
|
||||
'state': GObject.ParamSpec.uint('state', 'state', 'state',
|
||||
GObject.ParamFlags.READABLE,
|
||||
null),
|
||||
},
|
||||
}, class UpdateManager extends GObject.Object {
|
||||
_init() {
|
||||
super._init();
|
||||
|
||||
this._activeConnection = null;
|
||||
this._settingChangedSignalId = 0;
|
||||
this._updateTimeoutId = 0;
|
||||
|
||||
this._state = State.UNKNOWN;
|
||||
|
||||
NM.Client.new_async(null, this._clientGot.bind(this));
|
||||
}
|
||||
|
||||
_clientGot(obj, result) {
|
||||
this._client = NM.Client.new_finish(result);
|
||||
|
||||
this._client.connect('notify::primary-connection', this._sync.bind(this));
|
||||
this._client.connect('notify::state', this._sync.bind(this));
|
||||
|
||||
// Start retrieving the Mogwai proxy
|
||||
this._proxy = new SchedulerProxy(Gio.DBus.system,
|
||||
'com.endlessm.MogwaiSchedule1',
|
||||
'/com/endlessm/DownloadManager1',
|
||||
(proxy, error) => {
|
||||
if (error) {
|
||||
log(error.message);
|
||||
return;
|
||||
}
|
||||
this._proxy.connect('g-properties-changed',
|
||||
this._sync.bind(this));
|
||||
this._updateStatus();
|
||||
});
|
||||
|
||||
this._sync();
|
||||
}
|
||||
|
||||
_sync() {
|
||||
if (!this._client || !this._proxy)
|
||||
return;
|
||||
|
||||
if (this._updateTimeoutId > 0) {
|
||||
GLib.source_remove(this._updateTimeoutId);
|
||||
this._updateTimeoutId = 0;
|
||||
}
|
||||
|
||||
// Intermediate states (connecting or disconnecting) must not trigger
|
||||
// any kind of state change.
|
||||
if (this._client.state == NM.State.CONNECTING || this._client.state == NM.State.DISCONNECTING)
|
||||
return;
|
||||
|
||||
// Use a timeout to avoid instantly throwing the notification at
|
||||
// the user's face, and to avoid a series of unecessary updates
|
||||
// that happen when NetworkManager is still figuring out details.
|
||||
this._updateTimeoutId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT,
|
||||
2,
|
||||
() => {
|
||||
this._updateStatus();
|
||||
this._updateTimeoutId = 0;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
});
|
||||
GLib.Source.set_name_by_id(this._updateTimeoutId, '[update] updateStatus');
|
||||
}
|
||||
|
||||
_updateStatus() {
|
||||
// Update the current active connection. This will connect to the
|
||||
// NM.SettingUser signal to sync every time someone updates the
|
||||
// NM_SETTING_ALLOW_DOWNLOADS setting.
|
||||
this._updateActiveConnection();
|
||||
|
||||
let state = this._getState();
|
||||
if (state != this._state) {
|
||||
this._state = state;
|
||||
this.notify('state');
|
||||
|
||||
this._updateIcon();
|
||||
}
|
||||
}
|
||||
|
||||
_updateActiveConnection() {
|
||||
let currentActiveConnection = this._getActiveConnection();
|
||||
|
||||
if (this._activeConnection == currentActiveConnection)
|
||||
return;
|
||||
|
||||
// Disconnect from the previous active connection
|
||||
if (this._settingChangedSignalId > 0) {
|
||||
this._activeConnection.disconnect(this._settingChangedSignalId);
|
||||
this._settingChangedSignalId = 0;
|
||||
}
|
||||
|
||||
this._activeConnection = currentActiveConnection;
|
||||
|
||||
// Connect from the current active connection
|
||||
if (currentActiveConnection)
|
||||
this._settingChangedSignalId = currentActiveConnection.connect('changed', this._updateStatus.bind(this));
|
||||
}
|
||||
|
||||
_ensureUserSetting(connection) {
|
||||
let userSetting = connection.get_setting(NM.SettingUser.$gtype);
|
||||
if (!userSetting) {
|
||||
userSetting = new NM.SettingUser();
|
||||
connection.add_setting(userSetting);
|
||||
}
|
||||
return userSetting;
|
||||
}
|
||||
|
||||
_getState() {
|
||||
if (!this._activeConnection)
|
||||
return State.DISCONNECTED;
|
||||
|
||||
let userSetting = this._ensureUserSetting(this._activeConnection);
|
||||
|
||||
// We only return true when:
|
||||
// * Automatic Updates are on
|
||||
// * A schedule was set
|
||||
// * Something is being downloaded
|
||||
|
||||
let allowDownloadsValue = userSetting.get_data(NM_SETTING_ALLOW_DOWNLOADS);
|
||||
if (allowDownloadsValue) {
|
||||
let allowDownloads = (allowDownloadsValue === '1');
|
||||
|
||||
if (!allowDownloads)
|
||||
return State.DISABLED;
|
||||
} else {
|
||||
// Guess the default value from the metered state. Only return
|
||||
// if it's disabled - if it's not, we want to follow the regular
|
||||
// code paths and fetch the correct state
|
||||
let connectionSetting = this._activeConnection.get_setting_connection();
|
||||
|
||||
if (!connectionSetting)
|
||||
return State.DISABLED;
|
||||
|
||||
let metered = connectionSetting.get_metered();
|
||||
if (metered == NM.Metered.YES || metered == NM.Metered.GUESS_YES)
|
||||
return State.DISABLED;
|
||||
}
|
||||
|
||||
// Without the proxy, we can't really know the state
|
||||
if (!this._proxy)
|
||||
return State.UNKNOWN;
|
||||
|
||||
let scheduleSet = userSetting.get_data(NM_SETTING_TARIFF_ENABLED) === '1';
|
||||
if (!scheduleSet)
|
||||
return State.IDLE;
|
||||
|
||||
let downloading = this._proxy.ActiveEntryCount > 0;
|
||||
if (downloading)
|
||||
return State.DOWNLOADING;
|
||||
|
||||
// At this point we're not downloading anything, but something
|
||||
// might be queued
|
||||
let downloadsQueued = this._proxy.EntryCount > 0;
|
||||
if (downloadsQueued)
|
||||
return State.SCHEDULED;
|
||||
else
|
||||
return State.IDLE;
|
||||
}
|
||||
|
||||
_getActiveConnection() {
|
||||
let activeConnection = this._client.get_primary_connection();
|
||||
return activeConnection ? activeConnection.get_connection() : null;
|
||||
}
|
||||
|
||||
_updateIcon() {
|
||||
let state = this._state;
|
||||
let iconName = stateToIconName(state);
|
||||
|
||||
if (iconName) {
|
||||
let iconFile = Gio.File.new_for_uri(iconName);
|
||||
this._icon = new Gio.FileIcon({ file: iconFile });
|
||||
} else {
|
||||
this._icon = null;
|
||||
}
|
||||
|
||||
this.notify('icon');
|
||||
}
|
||||
|
||||
get state() {
|
||||
return this._state;
|
||||
}
|
||||
|
||||
get lastNotificationTime() {
|
||||
let connection = this._getActiveConnection();
|
||||
if (!connection)
|
||||
return -1;
|
||||
|
||||
let userSetting = connection.get_setting(NM.SettingUser.$gtype);
|
||||
if (!userSetting)
|
||||
return -1;
|
||||
|
||||
let time = userSetting.get_data(NM_SETTING_AUTOMATIC_UPDATES_NOTIFICATION_TIME);
|
||||
return time ? parseInt(time) : -1;
|
||||
}
|
||||
|
||||
set lastNotificationTime(time) {
|
||||
if (!this._activeConnection)
|
||||
return;
|
||||
|
||||
let userSetting = this._ensureUserSetting(this._activeConnection);
|
||||
userSetting.set_data(NM_SETTING_AUTOMATIC_UPDATES_NOTIFICATION_TIME,
|
||||
'%s'.format(time));
|
||||
|
||||
this._activeConnection.commit_changes(true, null);
|
||||
}
|
||||
|
||||
|
||||
get active() {
|
||||
return this._active;
|
||||
}
|
||||
|
||||
set active(_active) {
|
||||
if (this._active == _active)
|
||||
return;
|
||||
|
||||
this._active = _active;
|
||||
this.notify('active');
|
||||
}
|
||||
|
||||
get icon() {
|
||||
return this._icon;
|
||||
}
|
||||
|
||||
toggleAutomaticUpdates() {
|
||||
if (!this._activeConnection)
|
||||
return;
|
||||
|
||||
let userSetting = this._ensureUserSetting(this._activeConnection);
|
||||
|
||||
let state = this._getState();
|
||||
let value;
|
||||
|
||||
if (state == State.IDLE ||
|
||||
state == State.SCHEDULED ||
|
||||
state == State.DOWNLOADING) {
|
||||
value = '0';
|
||||
} else {
|
||||
value = '1';
|
||||
}
|
||||
|
||||
userSetting.set_data(NM_SETTING_ALLOW_DOWNLOADS, value);
|
||||
|
||||
this._activeConnection.commit_changes_async(true, null, (con, res, data) => {
|
||||
this._activeConnection.commit_changes_finish(res);
|
||||
this._updateStatus();
|
||||
});
|
||||
}
|
||||
});
|
135
js/ui/components/updates.js
Normal file
135
js/ui/components/updates.js
Normal file
@@ -0,0 +1,135 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
//
|
||||
// Copyright (C) 2018 Endless Mobile, Inc.
|
||||
//
|
||||
// This is a GNOME Shell component to wrap the interactions over
|
||||
// D-Bus with the Mogwai system daemon.
|
||||
//
|
||||
// Licensed under the GNU General Public License Version 2
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
const { Gio, GLib, Shell } = imports.gi;
|
||||
|
||||
const UpdateManager = imports.misc.updateManager;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const MessageTray = imports.ui.messageTray;
|
||||
|
||||
var UpdateComponent = class {
|
||||
constructor() {
|
||||
this._notification = null;
|
||||
this._state = UpdateManager.State.UNKNOWN;
|
||||
|
||||
this._manager = UpdateManager.getUpdateManager();
|
||||
this._manager.connect('notify::state', this._updateState.bind(this));
|
||||
|
||||
this._updateState();
|
||||
}
|
||||
|
||||
enable() {
|
||||
}
|
||||
|
||||
disable() {
|
||||
}
|
||||
|
||||
_updateState() {
|
||||
let newState = this._manager.state;
|
||||
|
||||
if (this._state == newState)
|
||||
return;
|
||||
|
||||
this._updateNotification(newState);
|
||||
this._state = newState;
|
||||
}
|
||||
|
||||
_updateNotification(newState) {
|
||||
// Don't notify when starting up
|
||||
if (this._manager.state == UpdateManager.State.UNKNOWN)
|
||||
return;
|
||||
|
||||
let alreadySentNotification = this._manager.lastNotificationTime != -1;
|
||||
|
||||
let wasDisconnected = this._state == UpdateManager.State.DISCONNECTED;
|
||||
let wasActive = this._state >= UpdateManager.State.IDLE;
|
||||
let isActive = newState >= UpdateManager.State.IDLE;
|
||||
|
||||
// The criteria to notify about the Automatic Updates setting is:
|
||||
// 1. If the user was disconnected and connects to a new network; or
|
||||
// 2. If the user was connected and connects to a network with different status;
|
||||
if ((wasDisconnected && alreadySentNotification) || (!wasDisconnected && isActive == wasActive))
|
||||
return;
|
||||
|
||||
if (this._notification)
|
||||
this._notification.destroy();
|
||||
|
||||
if (newState == UpdateManager.State.DISCONNECTED)
|
||||
return;
|
||||
|
||||
let source = new MessageTray.SystemNotificationSource();
|
||||
Main.messageTray.add(source);
|
||||
|
||||
// Figure out the title, subtitle and icon
|
||||
let title, subtitle, iconFile;
|
||||
|
||||
if (isActive) {
|
||||
title = _("Automatic updates on");
|
||||
subtitle = _("Your connection has unlimited data so automatic updates have been turned on.");
|
||||
iconFile = UpdateManager.stateToIconName(UpdateManager.State.IDLE);
|
||||
} else {
|
||||
title = _("Automatic updates are turned off to save your data");
|
||||
subtitle = _("You will need to choose which updates to apply when on this connection.");
|
||||
iconFile = UpdateManager.stateToIconName(UpdateManager.State.DISABLED);
|
||||
}
|
||||
|
||||
let gicon = new Gio.FileIcon({ file: Gio.File.new_for_uri(iconFile) });
|
||||
|
||||
// Create the notification.
|
||||
// The first time we notify the user for a given connection,
|
||||
// we set the urgency to critical so that we make sure the
|
||||
// user understands how we may be changing their settings.
|
||||
// On subsequent notifications for the given connection,
|
||||
// for instance if the user regularly switches between
|
||||
// metered and unmetered connections, we set the urgency
|
||||
// to normal so as not to be too obtrusive.
|
||||
this._notification = new MessageTray.Notification(source, title, subtitle, { gicon: gicon });
|
||||
this._notification.setUrgency(alreadySentNotification ?
|
||||
MessageTray.Urgency.NORMAL : MessageTray.Urgency.CRITICAL);
|
||||
this._notification.setTransient(false);
|
||||
|
||||
this._notification.addAction(_("Close"), () => {
|
||||
this._notification.destroy();
|
||||
});
|
||||
|
||||
this._notification.addAction(_("Change Settings…"), () => {
|
||||
// FIXME: this requires the Automatic Updates panel in GNOME
|
||||
// Settings. Going with the Network panel for now…
|
||||
let app = Shell.AppSystem.get_default().lookup_app('gnome-network-panel.desktop');
|
||||
Main.overview.hide();
|
||||
app.activate();
|
||||
});
|
||||
|
||||
source.notify(this._notification);
|
||||
|
||||
this._notification.connect('destroy', () => {
|
||||
this._notification = null;
|
||||
});
|
||||
|
||||
// Now that we first detected this connection, mark it as such
|
||||
this._manager.lastNotificationTime = GLib.get_real_time();
|
||||
}
|
||||
};
|
||||
|
||||
var Component = UpdateComponent;
|
@@ -306,6 +306,9 @@ var _Draggable = class _Draggable {
|
||||
* for the draggable.
|
||||
*/
|
||||
startDrag(stageX, stageY, time, sequence, device) {
|
||||
if (currentDraggable)
|
||||
return;
|
||||
|
||||
if (device == undefined) {
|
||||
let event = Clutter.get_current_event();
|
||||
|
||||
@@ -447,7 +450,8 @@ var _Draggable = class _Draggable {
|
||||
let [stageX, stageY] = event.get_coords();
|
||||
|
||||
// See if the user has moved the mouse enough to trigger a drag
|
||||
let threshold = St.Settings.get().drag_threshold;
|
||||
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
||||
let threshold = St.Settings.get().drag_threshold * scaleFactor;
|
||||
if (!currentDraggable &&
|
||||
(Math.abs(stageX - this._dragStartX) > threshold ||
|
||||
Math.abs(stageY - this._dragStartY) > threshold)) {
|
||||
|
@@ -774,10 +774,17 @@ class AggregateMenu extends PanelMenu.Button {
|
||||
this._nightLight = new imports.ui.status.nightLight.Indicator();
|
||||
this._thunderbolt = new imports.ui.status.thunderbolt.Indicator();
|
||||
|
||||
if (Main.sessionMode.components.includes('updates'))
|
||||
this._automaticUpdates = new imports.ui.status.automaticUpdates.Indicator();
|
||||
else
|
||||
this._automaticUpdates = null;
|
||||
|
||||
this._indicators.add_child(this._thunderbolt.indicators);
|
||||
this._indicators.add_child(this._screencast.indicators);
|
||||
this._indicators.add_child(this._location.indicators);
|
||||
this._indicators.add_child(this._nightLight.indicators);
|
||||
if (this._automaticUpdates)
|
||||
this._indicators.add_child(this._automaticUpdates.indicators);
|
||||
if (this._network) {
|
||||
this._indicators.add_child(this._network.indicators);
|
||||
}
|
||||
@@ -796,6 +803,8 @@ class AggregateMenu extends PanelMenu.Button {
|
||||
if (this._network) {
|
||||
this.menu.addMenuItem(this._network.menu);
|
||||
}
|
||||
if (this._automaticUpdates)
|
||||
this.menu.addMenuItem(this._automaticUpdates.menu);
|
||||
if (this._bluetooth) {
|
||||
this.menu.addMenuItem(this._bluetooth.menu);
|
||||
}
|
||||
|
@@ -92,9 +92,11 @@ const _modes = {
|
||||
unlockDialog: imports.ui.unlockDialog.UnlockDialog,
|
||||
components: Config.HAVE_NETWORKMANAGER ?
|
||||
['networkAgent', 'polkitAgent', 'telepathyClient',
|
||||
'keyring', 'autorunManager', 'automountManager'] :
|
||||
'keyring', 'autorunManager', 'automountManager',
|
||||
'updates'] :
|
||||
['polkitAgent', 'telepathyClient',
|
||||
'keyring', 'autorunManager', 'automountManager'],
|
||||
'keyring', 'autorunManager', 'automountManager',
|
||||
'updates'],
|
||||
|
||||
panel: {
|
||||
left: ['activities', 'appMenu'],
|
||||
|
144
js/ui/status/automaticUpdates.js
Normal file
144
js/ui/status/automaticUpdates.js
Normal file
@@ -0,0 +1,144 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
//
|
||||
// Copyright (C) 2018 Endless Mobile, Inc.
|
||||
//
|
||||
// This is a GNOME Shell component to wrap the interactions over
|
||||
// D-Bus with the Mogwai system daemon.
|
||||
//
|
||||
// Licensed under the GNU General Public License Version 2
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
const { Gio, GLib, Shell, St } = imports.gi;
|
||||
|
||||
const UpdateManager = imports.misc.updateManager;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const MessageTray = imports.ui.messageTray;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
|
||||
const NM_SETTING_AUTOMATIC_UPDATES_NOTIFICATION_TIME = "connection.automatic-updates-notification-time";
|
||||
const NM_SETTING_ALLOW_DOWNLOADS = 'connection.allow-downloads';
|
||||
const NM_SETTING_TARIFF_ENABLED = "connection.tariff-enabled";
|
||||
|
||||
const SchedulerInterface = '\
|
||||
<node> \
|
||||
<interface name="com.endlessm.DownloadManager1.Scheduler"> \
|
||||
<property name="ActiveEntryCount" type="u" access="read" /> \
|
||||
<property name="EntryCount" type="u" access="read" /> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const SchedulerProxy = Gio.DBusProxy.makeProxyWrapper(SchedulerInterface);
|
||||
|
||||
var Indicator = class extends PanelMenu.SystemIndicator {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this._indicator = this._addIndicator();
|
||||
this._indicator.visible = false;
|
||||
|
||||
this._item = new PopupMenu.PopupSubMenuMenuItem("", true);
|
||||
this._toggleItem = this._item.menu.addAction("", this._toggleAutomaticUpdates.bind(this));
|
||||
this._item.menu.addAction(_("Updates Queue"), () => {
|
||||
let params = new GLib.Variant('(sava{sv})', [ 'set-mode', [ new GLib.Variant('s', 'updates') ], {} ]);
|
||||
Gio.DBus.session.call('org.gnome.Software',
|
||||
'/org/gnome/Software',
|
||||
'org.gtk.Actions',
|
||||
'Activate',
|
||||
params,
|
||||
null,
|
||||
Gio.DBusCallFlags.NONE,
|
||||
5000,
|
||||
null,
|
||||
(conn, result) => {
|
||||
try {
|
||||
conn.call_finish(result);
|
||||
} catch (e) {
|
||||
logError(e, 'Failed to start gnome-software');
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
this._item.menu.addSettingsAction(_("Set a Schedule"), 'gnome-updates-panel.desktop');
|
||||
this.menu.addMenuItem(this._item);
|
||||
|
||||
this._manager = UpdateManager.getUpdateManager();
|
||||
this._manager.connect('notify::state', this._updateState.bind(this));
|
||||
|
||||
this._updateState();
|
||||
}
|
||||
|
||||
_updateState() {
|
||||
this._updateStatus();
|
||||
}
|
||||
|
||||
_sessionUpdated() {
|
||||
let sensitive = !Main.sessionMode.isLocked && !Main.sessionMode.isGreeter;
|
||||
this.menu.setSensitive(sensitive);
|
||||
}
|
||||
|
||||
_updateStatus() {
|
||||
// Toggle item name
|
||||
this._updateItem();
|
||||
|
||||
// Icons
|
||||
let icon = this._getIcon()
|
||||
|
||||
this._item.icon.gicon = icon;
|
||||
this._indicator.gicon = icon;
|
||||
|
||||
// Only show the Automatic Updates icon at the bottom bar when it is
|
||||
// both enabled, and there are updates being downloaded or installed.
|
||||
this._updateVisibility();
|
||||
|
||||
// The status label
|
||||
this._item.label.text = _("Automatic Updates");
|
||||
}
|
||||
|
||||
_updateItem() {
|
||||
let state = this._manager.state;
|
||||
|
||||
if (state == UpdateManager.State.DISABLED)
|
||||
this._toggleItem.label.text = _("Turn On");
|
||||
else
|
||||
this._toggleItem.label.text = _("Turn Off");
|
||||
}
|
||||
|
||||
_toggleAutomaticUpdates() {
|
||||
this._manager.toggleAutomaticUpdates();
|
||||
}
|
||||
|
||||
_getIcon() {
|
||||
let state = this._manager.state;
|
||||
let iconName = UpdateManager.stateToIconName(state);
|
||||
|
||||
if (!iconName)
|
||||
return null;
|
||||
|
||||
let iconFile = Gio.File.new_for_uri(iconName);
|
||||
let gicon = new Gio.FileIcon({ file: iconFile });
|
||||
|
||||
return gicon;
|
||||
}
|
||||
|
||||
_updateVisibility() {
|
||||
let state = this._manager.state;
|
||||
|
||||
this._item.actor.visible = (state != UpdateManager.State.DISCONNECTED);
|
||||
this._indicator.visible = (state == UpdateManager.State.DOWNLOADING);
|
||||
}
|
||||
};
|
@@ -52,6 +52,7 @@ js/ui/search.js
|
||||
js/ui/shellEntry.js
|
||||
js/ui/shellMountOperation.js
|
||||
js/ui/status/accessibility.js
|
||||
js/ui/status/automaticUpdates.js
|
||||
js/ui/status/bluetooth.js
|
||||
js/ui/status/brightness.js
|
||||
js/ui/status/keyboard.js
|
||||
|
144
po/tg.po
144
po/tg.po
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Project-Id-Version: Tajik Gnome\n"
|
||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
|
||||
"POT-Creation-Date: 2019-03-02 10:57+0000\n"
|
||||
"PO-Revision-Date: 2019-03-06 20:14+0500\n"
|
||||
"PO-Revision-Date: 2019-03-13 21:44+0500\n"
|
||||
"Last-Translator: Victor Ibragimov <victor.ibragimov@gmail.com>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: tg\n"
|
||||
@@ -32,7 +32,7 @@ msgstr "Марказонидани огоҳии фаъол"
|
||||
|
||||
#: data/50-gnome-shell-system.xml:15
|
||||
msgid "Show the overview"
|
||||
msgstr "Намоиш додани хулоса"
|
||||
msgstr "Намоиш додани ҷамъбаст"
|
||||
|
||||
#: data/50-gnome-shell-system.xml:18
|
||||
msgid "Show all applications"
|
||||
@@ -82,7 +82,7 @@ msgstr "Ғайрифаъол кардани васеъшавиҳои корба
|
||||
|
||||
#: data/org.gnome.shell.gschema.xml.in:27
|
||||
msgid "Disable all extensions the user has enabled without affecting the “enabled-extension” setting."
|
||||
msgstr ""
|
||||
msgstr "Ҳамаи васеъшавиҳое, ки корбар фаъол кард, бе расонидани таъсир ба танзими “васеъшавиии-фаъол” ғайрифаъол карда мешаванд."
|
||||
|
||||
#: data/org.gnome.shell.gschema.xml.in:34
|
||||
msgid "Disables the validation of extension version compatibility"
|
||||
@@ -188,11 +188,11 @@ msgstr "Тугмабандӣ барои иваз кардани намоёнии
|
||||
|
||||
#: data/org.gnome.shell.gschema.xml.in:138
|
||||
msgid "Keybinding to focus the active notification"
|
||||
msgstr "Тугмабандӣ барои гузоштани фокус ба огоҳии фаъол"
|
||||
msgstr "Тугмабандӣ барои марказонидани огоҳии фаъол"
|
||||
|
||||
#: data/org.gnome.shell.gschema.xml.in:139
|
||||
msgid "Keybinding to focus the active notification."
|
||||
msgstr "Тугмабандӣ барои гузоштани фокус ба огоҳии фаъол."
|
||||
msgstr "Тугмабандӣ барои марказонидани огоҳии фаъол."
|
||||
|
||||
#: data/org.gnome.shell.gschema.xml.in:145
|
||||
msgid "Keybinding that pauses and resumes all running tweens, for debugging purposes"
|
||||
@@ -245,11 +245,11 @@ msgstr "Гузариш ба барномаи 9"
|
||||
|
||||
#: data/org.gnome.shell.gschema.xml.in:190
|
||||
msgid "Which keyboard to use"
|
||||
msgstr "Клавиатураро интихоб кунед"
|
||||
msgstr "Клавиатураро интихоб намоед"
|
||||
|
||||
#: data/org.gnome.shell.gschema.xml.in:191
|
||||
msgid "The type of keyboard to use."
|
||||
msgstr "Намуди клавиатура барои истифода."
|
||||
msgstr "Навъи клавиатурае, ки истифода мешавад."
|
||||
|
||||
#: data/org.gnome.shell.gschema.xml.in:202
|
||||
#: data/org.gnome.shell.gschema.xml.in:229
|
||||
@@ -308,15 +308,15 @@ msgstr "Воридшавии шабакавӣ"
|
||||
#. Translators: Do NOT translate or transliterate this text (this is an icon file name)!
|
||||
#: data/org.gnome.Shell.PortalHelper.desktop.in.in:9
|
||||
msgid "network-workgroup"
|
||||
msgstr ""
|
||||
msgstr "шабака-гурӯҳи корӣ"
|
||||
|
||||
#: js/extensionPrefs/main.js:116
|
||||
msgid "Something’s gone wrong"
|
||||
msgstr ""
|
||||
msgstr "Чизе нодуруст ба миён омад"
|
||||
|
||||
#: js/extensionPrefs/main.js:123
|
||||
msgid "We’re very sorry, but there’s been a problem: the settings for this extension can’t be displayed. We recommend that you report the issue to the extension authors."
|
||||
msgstr ""
|
||||
msgstr "Мутаассифона, хатое ба вуҷуд омад: танзимот барои ин васеъшавӣ нишон дода намешавад. Тавсия дода мешавад, ки шумо дар бораи хато ба муаллифони васеъшавӣ гузориш диҳед."
|
||||
|
||||
#: js/extensionPrefs/main.js:130
|
||||
#| msgid "Show Details"
|
||||
@@ -330,7 +330,7 @@ msgstr "Намоиш додани хатоҳо"
|
||||
|
||||
#: js/extensionPrefs/main.js:185
|
||||
msgid "Homepage"
|
||||
msgstr ""
|
||||
msgstr "Саҳифаи асосӣ"
|
||||
|
||||
#: js/extensionPrefs/main.js:186
|
||||
#| msgid "UUIDs of extensions to enable"
|
||||
@@ -340,15 +340,15 @@ msgstr "Рамзҳои UUID барои пасвандҳои фаъолшаван
|
||||
#: js/extensionPrefs/main.js:449
|
||||
#| msgid "No extensions installed"
|
||||
msgid "No Extensions Installed"
|
||||
msgstr "Ягон пасванд насб нашудааст"
|
||||
msgstr "Ягон васеъшавӣ насб нашудааст"
|
||||
|
||||
#: js/extensionPrefs/main.js:459
|
||||
msgid "Extensions can be installed through Software or <a href=\"https://extensions.gnome.org\">extensions.gnome.org</a>."
|
||||
msgstr ""
|
||||
msgstr "Васеъшавиҳо ба воситаи низоми нармафзор ё <a href=\"https://extensions.gnome.org\">extensions.gnome.org</a> ҷорӣ карда мешаванд."
|
||||
|
||||
#: js/extensionPrefs/main.js:474
|
||||
msgid "Browse in Software"
|
||||
msgstr ""
|
||||
msgstr "Намоиш дар низоми нармафзор"
|
||||
|
||||
#: js/gdm/authPrompt.js:140 js/ui/audioDeviceSelection.js:55
|
||||
#: js/ui/components/networkAgent.js:117 js/ui/components/polkitAgent.js:136
|
||||
@@ -430,7 +430,7 @@ msgstr ""
|
||||
#: js/misc/systemActions.js:95
|
||||
msgctxt "search-result"
|
||||
msgid "Lock Screen"
|
||||
msgstr ""
|
||||
msgstr "Қулф кардани экран"
|
||||
|
||||
#. Translators: A list of keywords that match the lock screen action, separated by semicolons
|
||||
#: js/misc/systemActions.js:98
|
||||
@@ -454,13 +454,13 @@ msgstr ""
|
||||
#| msgid "Suspend"
|
||||
msgctxt "search-result"
|
||||
msgid "Suspend"
|
||||
msgstr "Таваққуф кардан"
|
||||
msgstr "Таваққуф кардани низом"
|
||||
|
||||
#. Translators: A list of keywords that match the suspend action, separated by semicolons
|
||||
#: js/misc/systemActions.js:112
|
||||
#| msgid "Suspend"
|
||||
msgid "suspend;sleep"
|
||||
msgstr "Таваққуф"
|
||||
msgstr "таваққуф;хоб"
|
||||
|
||||
#. Translators: The name of the switch user action in search
|
||||
#: js/misc/systemActions.js:116
|
||||
@@ -473,14 +473,14 @@ msgstr "Иваз кардани корбар"
|
||||
#: js/misc/systemActions.js:119
|
||||
#| msgid "Switch User"
|
||||
msgid "switch user"
|
||||
msgstr "Таъвизи корбар"
|
||||
msgstr "ивази корбар"
|
||||
|
||||
#. Translators: The name of the lock orientation action in search
|
||||
#: js/misc/systemActions.js:123
|
||||
#| msgid "Orientation Lock"
|
||||
msgctxt "search-result"
|
||||
msgid "Lock Orientation"
|
||||
msgstr "Қулфи самт"
|
||||
msgstr "Қулфи самти экран"
|
||||
|
||||
#. Translators: A list of keywords that match the lock orientation action, separated by semicolons
|
||||
#: js/misc/systemActions.js:126
|
||||
@@ -504,7 +504,7 @@ msgstr "Иҷрокунии “%s” қатъ шудааст:"
|
||||
|
||||
#: js/misc/util.js:175
|
||||
msgid "Just now"
|
||||
msgstr ""
|
||||
msgstr "Ҳоли ҳозир"
|
||||
|
||||
#: js/misc/util.js:177
|
||||
#, javascript-format
|
||||
@@ -533,29 +533,29 @@ msgstr "Дирӯз"
|
||||
#, javascript-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[0] "%d рӯз пеш"
|
||||
msgstr[1] "%d рӯз пеш"
|
||||
|
||||
#: js/misc/util.js:188
|
||||
#, javascript-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[0] "%d ҳафта пеш"
|
||||
msgstr[1] "%d ҳафта пеш"
|
||||
|
||||
#: js/misc/util.js:191
|
||||
#, javascript-format
|
||||
msgid "%d month ago"
|
||||
msgid_plural "%d months ago"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[0] "%d моҳ пеш"
|
||||
msgstr[1] "%d моҳ пеш"
|
||||
|
||||
#: js/misc/util.js:193
|
||||
#, javascript-format
|
||||
msgid "%d year ago"
|
||||
msgid_plural "%d years ago"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[0] "%d сол пеш"
|
||||
msgstr[1] "%d сол пеш"
|
||||
|
||||
#. Translators: Time in 24h format
|
||||
#: js/misc/util.js:223
|
||||
@@ -635,22 +635,22 @@ msgstr "%B %d %Y, %l∶%M %p"
|
||||
#: js/portalHelper/main.js:40
|
||||
#| msgid "Hotspot Active"
|
||||
msgid "Hotspot Login"
|
||||
msgstr "Hotspot фаъол аст"
|
||||
msgstr "Воридшавӣ ба нуқтаи пайваст"
|
||||
|
||||
#: js/portalHelper/main.js:86
|
||||
msgid "Your connection to this hotspot login is not secure. Passwords or other information you enter on this page can be viewed by people nearby."
|
||||
msgstr ""
|
||||
msgstr "Пайвасти воридшавии шумо ба нуқтаи пайвасти ҷорӣ бехатар намебошад. Ниҳонвожаҳо ё маълумоти дигаре, ки дар ин саҳифа ворид карда мешавад, метавонанд бо одамони дар гидру атроф ошкор карда шаванд."
|
||||
|
||||
#. No support for non-modal system dialogs, so ignore the option
|
||||
#. let modal = options['modal'] || true;
|
||||
#: js/ui/accessDialog.js:37 js/ui/status/location.js:360
|
||||
msgid "Deny Access"
|
||||
msgstr ""
|
||||
msgstr "Манъ кардани дастрасӣ"
|
||||
|
||||
#: js/ui/accessDialog.js:38 js/ui/status/location.js:363
|
||||
#| msgid "Always grant access"
|
||||
msgid "Grant Access"
|
||||
msgstr "Ҳамеша иҷозат додан"
|
||||
msgstr "Иҷозат додани дастрасӣ"
|
||||
|
||||
#: js/ui/appDisplay.js:660
|
||||
msgid "Frequently used applications will appear here"
|
||||
@@ -697,7 +697,7 @@ msgstr "%s аз баргузидаҳои шумо тоза шудааст."
|
||||
#: js/ui/audioDeviceSelection.js:42
|
||||
#| msgid "Send Files to Device…"
|
||||
msgid "Select Audio Device"
|
||||
msgstr "Фиристодани файлҳо ба дастгоҳ..."
|
||||
msgstr "Интихоби дастгоҳи аудиоӣ"
|
||||
|
||||
#: js/ui/audioDeviceSelection.js:53
|
||||
msgid "Sound Settings"
|
||||
@@ -705,11 +705,11 @@ msgstr "Танзимоти садо"
|
||||
|
||||
#: js/ui/audioDeviceSelection.js:62
|
||||
msgid "Headphones"
|
||||
msgstr ""
|
||||
msgstr "Гӯшмонакҳо"
|
||||
|
||||
#: js/ui/audioDeviceSelection.js:64
|
||||
msgid "Headset"
|
||||
msgstr ""
|
||||
msgstr "Гӯшмонак бо микрофон"
|
||||
|
||||
#: js/ui/audioDeviceSelection.js:66 js/ui/status/volume.js:247
|
||||
msgid "Microphone"
|
||||
@@ -717,7 +717,7 @@ msgstr "Микрофон"
|
||||
|
||||
#: js/ui/backgroundMenu.js:13
|
||||
msgid "Change Background…"
|
||||
msgstr "Тағйир додани пазсамина..."
|
||||
msgstr "Тағйир додани пазсамина…"
|
||||
|
||||
#: js/ui/backgroundMenu.js:15 js/ui/status/nightLight.js:43
|
||||
msgid "Display Settings"
|
||||
@@ -800,7 +800,7 @@ msgstr "%OB"
|
||||
#.
|
||||
#: js/ui/calendar.js:342
|
||||
msgid "%OB %Y"
|
||||
msgstr ""
|
||||
msgstr "%OB %Y"
|
||||
|
||||
#: js/ui/calendar.js:399
|
||||
msgid "Previous month"
|
||||
@@ -854,14 +854,14 @@ msgstr "Ягон рӯйдод нест"
|
||||
|
||||
#: js/ui/calendar.js:1075
|
||||
msgid "Clear"
|
||||
msgstr ""
|
||||
msgstr "Пок кардан"
|
||||
|
||||
#. Translators: %s is an application name
|
||||
#: js/ui/closeDialog.js:42
|
||||
#, javascript-format
|
||||
#| msgid "“%s” is ready"
|
||||
msgid "“%s” is not responding."
|
||||
msgstr "“%s” омода аст"
|
||||
msgstr "“%s” ҷавоб намедиҳад."
|
||||
|
||||
#: js/ui/closeDialog.js:43
|
||||
msgid "You may choose to wait a short while for it to continue or force the application to quit entirely."
|
||||
@@ -869,11 +869,11 @@ msgstr ""
|
||||
|
||||
#: js/ui/closeDialog.js:59
|
||||
msgid "Force Quit"
|
||||
msgstr ""
|
||||
msgstr "Маҷбуран пӯшида шавад"
|
||||
|
||||
#: js/ui/closeDialog.js:62
|
||||
msgid "Wait"
|
||||
msgstr ""
|
||||
msgstr "Интизор шавед"
|
||||
|
||||
#: js/ui/components/automountManager.js:86
|
||||
msgid "External drive connected"
|
||||
@@ -910,24 +910,24 @@ msgstr "Пайваст шудан"
|
||||
#: js/ui/components/networkAgent.js:246 js/ui/components/networkAgent.js:265
|
||||
#: js/ui/components/networkAgent.js:285 js/ui/components/networkAgent.js:295
|
||||
msgid "Password: "
|
||||
msgstr "Ниҳонвожа:"
|
||||
msgstr "Ниҳонвожа: "
|
||||
|
||||
#. static WEP
|
||||
#: js/ui/components/networkAgent.js:216
|
||||
msgid "Key: "
|
||||
msgstr "Калид:"
|
||||
msgstr "Калид: "
|
||||
|
||||
#: js/ui/components/networkAgent.js:249 js/ui/components/networkAgent.js:271
|
||||
msgid "Private key password: "
|
||||
msgstr "Пароли калиди шахсӣ:"
|
||||
msgstr "Ниҳонвожаи калиди шахсӣ: "
|
||||
|
||||
#: js/ui/components/networkAgent.js:269
|
||||
msgid "Identity: "
|
||||
msgstr "Шахсият:"
|
||||
msgstr "Шахсият: "
|
||||
|
||||
#: js/ui/components/networkAgent.js:283
|
||||
msgid "Service: "
|
||||
msgstr "Хидмат:"
|
||||
msgstr "Хидмат: "
|
||||
|
||||
#: js/ui/components/networkAgent.js:312 js/ui/components/networkAgent.js:685
|
||||
msgid "Authentication required by wireless network"
|
||||
@@ -944,7 +944,7 @@ msgstr "Санҷиши ҳаққонияти 802.1X-и симдор"
|
||||
|
||||
#: js/ui/components/networkAgent.js:319
|
||||
msgid "Network name: "
|
||||
msgstr "Номи шабака:"
|
||||
msgstr "Номи шабака: "
|
||||
|
||||
#: js/ui/components/networkAgent.js:324 js/ui/components/networkAgent.js:693
|
||||
msgid "DSL authentication"
|
||||
@@ -960,7 +960,7 @@ msgstr "Барои дастгоҳи паҳннавори мобилӣ рамзи
|
||||
|
||||
#: js/ui/components/networkAgent.js:333
|
||||
msgid "PIN: "
|
||||
msgstr "PIN:"
|
||||
msgstr "PIN: "
|
||||
|
||||
#: js/ui/components/networkAgent.js:340 js/ui/components/networkAgent.js:706
|
||||
msgid "Mobile broadband network password"
|
||||
@@ -1051,12 +1051,12 @@ msgstr "Обу ҳаво"
|
||||
#: js/ui/dateMenu.js:305
|
||||
#| msgid "Select a network"
|
||||
msgid "Select a location…"
|
||||
msgstr "Интихоб кардани шабака"
|
||||
msgstr "Интихоби ҷойгиршавӣ…"
|
||||
|
||||
#: js/ui/dateMenu.js:313
|
||||
#| msgid "Searching…"
|
||||
msgid "Loading…"
|
||||
msgstr "Ҷустуҷӯ рафта истодааст..."
|
||||
msgstr "Бор шуда истодааст…"
|
||||
|
||||
#: js/ui/dateMenu.js:323
|
||||
msgid "Go online for weather information"
|
||||
@@ -1274,7 +1274,7 @@ msgstr ""
|
||||
|
||||
#: js/ui/kbdA11yDialog.js:57
|
||||
msgid "Leave On"
|
||||
msgstr ""
|
||||
msgstr "Ҳамеша фаъол"
|
||||
|
||||
#: js/ui/kbdA11yDialog.js:57 js/ui/status/bluetooth.js:133
|
||||
#: js/ui/status/network.js:1264
|
||||
@@ -1287,11 +1287,11 @@ msgstr "Фаъол кардан"
|
||||
#: js/ui/status/nightLight.js:39 js/ui/status/rfkill.js:79
|
||||
#: js/ui/status/rfkill.js:106
|
||||
msgid "Turn Off"
|
||||
msgstr "Хомӯш кардан"
|
||||
msgstr "Ғайрифаъол кардан"
|
||||
|
||||
#: js/ui/kbdA11yDialog.js:65
|
||||
msgid "Leave Off"
|
||||
msgstr ""
|
||||
msgstr "Ҳамеша ғайрифаъол"
|
||||
|
||||
#: js/ui/keyboard.js:203
|
||||
msgid "Region & Language Settings"
|
||||
@@ -1327,7 +1327,7 @@ msgstr "Ғайрифаъол"
|
||||
|
||||
#: js/ui/lookingGlass.js:693
|
||||
msgid "Error"
|
||||
msgstr "Хатогӣ"
|
||||
msgstr "Хато"
|
||||
|
||||
#: js/ui/lookingGlass.js:695
|
||||
msgid "Out of date"
|
||||
@@ -1372,7 +1372,7 @@ msgstr "Ботил сохтан"
|
||||
#. activities. See also note for "Activities" string.
|
||||
#: js/ui/overview.js:100
|
||||
msgid "Overview"
|
||||
msgstr "Хулоса"
|
||||
msgstr "Ҷамъбаст"
|
||||
|
||||
#. Translators: this is the text displayed
|
||||
#. in the search entry when no search is
|
||||
@@ -1380,20 +1380,20 @@ msgstr "Хулоса"
|
||||
#. characters.
|
||||
#: js/ui/overview.js:226
|
||||
msgid "Type to search…"
|
||||
msgstr "Ҷустуҷӯ кардан..."
|
||||
msgstr "Барои ҷустуҷӯ чизеро чоп намоед…"
|
||||
|
||||
#: js/ui/padOsd.js:92
|
||||
msgid "New shortcut…"
|
||||
msgstr ""
|
||||
msgstr "Миёнбури нав…"
|
||||
|
||||
#: js/ui/padOsd.js:141
|
||||
#| msgid "Applications"
|
||||
msgid "Application defined"
|
||||
msgstr "Барномаҳо"
|
||||
msgstr "Барномаи муайяншуда"
|
||||
|
||||
#: js/ui/padOsd.js:142
|
||||
msgid "Show on-screen help"
|
||||
msgstr ""
|
||||
msgstr "Намоиш додани кумаки экранӣ"
|
||||
|
||||
#: js/ui/padOsd.js:143
|
||||
#| msgid "Switch User"
|
||||
@@ -1406,7 +1406,7 @@ msgstr ""
|
||||
|
||||
#: js/ui/padOsd.js:209
|
||||
msgid "Done"
|
||||
msgstr ""
|
||||
msgstr "Тайёр"
|
||||
|
||||
#: js/ui/padOsd.js:721
|
||||
msgid "Edit…"
|
||||
@@ -1414,19 +1414,19 @@ msgstr "Таҳрир кардан…"
|
||||
|
||||
#: js/ui/padOsd.js:763 js/ui/padOsd.js:868
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
msgstr "Ҳеҷ"
|
||||
|
||||
#: js/ui/padOsd.js:822
|
||||
msgid "Press a button to configure"
|
||||
msgstr ""
|
||||
msgstr "Барои идома тугмаеро пахш намоед"
|
||||
|
||||
#: js/ui/padOsd.js:823
|
||||
msgid "Press Esc to exit"
|
||||
msgstr ""
|
||||
msgstr "Барои баромад тугмаи Esc-ро пахш намоед"
|
||||
|
||||
#: js/ui/padOsd.js:826
|
||||
msgid "Press any key to exit"
|
||||
msgstr ""
|
||||
msgstr "Барои баромад тугмаи дилхоҳро пахш намоед"
|
||||
|
||||
#: js/ui/panel.js:108
|
||||
msgid "Quit"
|
||||
@@ -1446,7 +1446,7 @@ msgstr "Низом"
|
||||
|
||||
#: js/ui/panel.js:861
|
||||
msgid "Top Bar"
|
||||
msgstr "Панели боло"
|
||||
msgstr "Лавҳаии болоӣ"
|
||||
|
||||
#. Translators: this MUST be either "toggle-switch-us"
|
||||
#. (for toggle switches containing the English words
|
||||
@@ -1519,7 +1519,7 @@ msgstr "Қулф аз тарави барнома баста шудааст"
|
||||
|
||||
#: js/ui/search.js:635
|
||||
msgid "Searching…"
|
||||
msgstr "Ҷустуҷӯ рафта истодааст..."
|
||||
msgstr "Дар ҳоли ҷустуҷӯ…"
|
||||
|
||||
#: js/ui/search.js:637
|
||||
msgid "No results."
|
||||
@@ -1836,7 +1836,7 @@ msgstr "%s пайваст нашудааст"
|
||||
#: js/ui/status/network.js:1393
|
||||
#| msgid "Connecting"
|
||||
msgid "connecting…"
|
||||
msgstr "Пайвастшавӣ"
|
||||
msgstr "пайваст шуда истодааст…"
|
||||
|
||||
#. Translators: this is for network connections that require some kind of key or password
|
||||
#: js/ui/status/network.js:1396
|
||||
@@ -1894,7 +1894,7 @@ msgstr "Пайваст қатъ шудааст"
|
||||
|
||||
#: js/ui/status/network.js:1703
|
||||
msgid "Activation of network connection failed"
|
||||
msgstr "Фаъолсозии пайвасти шабака қатъ шудааст."
|
||||
msgstr "Фаъолсозии пайвасти шабака қатъ шуд"
|
||||
|
||||
#: js/ui/status/nightLight.js:60
|
||||
#| msgid "Networking is disabled"
|
||||
@@ -1929,7 +1929,7 @@ msgstr ""
|
||||
#. to estimate battery life
|
||||
#: js/ui/status/power.js:70 js/ui/status/power.js:76
|
||||
msgid "Estimating…"
|
||||
msgstr "Ҳисоб шуда истодааст..."
|
||||
msgstr "Ҳисоб шуда истодааст…"
|
||||
|
||||
#. Translators: this is <hours>:<minutes> Remaining (<percentage>)
|
||||
#: js/ui/status/power.js:84
|
||||
@@ -1948,7 +1948,7 @@ msgstr "%d∶%02d то пур шудан (%d%%)"
|
||||
#: js/ui/status/power.js:117 js/ui/status/power.js:119
|
||||
#, javascript-format
|
||||
msgid "%d %%"
|
||||
msgstr ""
|
||||
msgstr "%d %%"
|
||||
|
||||
#: js/ui/status/remoteAccess.js:42
|
||||
msgid "Screen is Being Shared"
|
||||
@@ -1978,11 +1978,11 @@ msgstr "Баромад аз мизи корӣ"
|
||||
#: js/ui/status/system.js:227
|
||||
#| msgid "Sound Settings"
|
||||
msgid "Account Settings"
|
||||
msgstr "Танзимоти садо"
|
||||
msgstr "Танзимоти ҳисоб"
|
||||
|
||||
#: js/ui/status/system.js:255
|
||||
msgid "Orientation Lock"
|
||||
msgstr "Қулфи самт"
|
||||
msgstr "Қулфи самти экран"
|
||||
|
||||
#: js/ui/status/system.js:281
|
||||
msgid "Suspend"
|
||||
|
Reference in New Issue
Block a user