mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-20 23:54:26 +08:00
fead.添加了电源菜单
This commit is contained in:
165
LanMountainDesktop.PluginSdk/LICENSE
Normal file
165
LanMountainDesktop.PluginSdk/LICENSE
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|
||||||
|
This version of the GNU Lesser General Public License incorporates
|
||||||
|
the terms and conditions of version 3 of the GNU General Public
|
||||||
|
License, supplemented by the additional permissions listed below.
|
||||||
|
|
||||||
|
0. Additional Definitions.
|
||||||
|
|
||||||
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
|
General Public License.
|
||||||
|
|
||||||
|
"The Library" refers to a covered work governed by this License,
|
||||||
|
other than an Application or a Combined Work as defined below.
|
||||||
|
|
||||||
|
An "Application" is any work that makes use of an interface provided
|
||||||
|
by the Library, but which is not otherwise based on the Library.
|
||||||
|
Defining a subclass of a class defined by the Library is deemed a mode
|
||||||
|
of using an interface provided by the Library.
|
||||||
|
|
||||||
|
A "Combined Work" is a work produced by combining or linking an
|
||||||
|
Application with the Library. The particular version of the Library
|
||||||
|
with which the Combined Work was made is also called the "Linked
|
||||||
|
Version".
|
||||||
|
|
||||||
|
The "Minimal Corresponding Source" for a Combined Work means the
|
||||||
|
Corresponding Source for the Combined Work, excluding any source code
|
||||||
|
for portions of the Combined Work that, considered in isolation, are
|
||||||
|
based on the Application, and not on the Linked Version.
|
||||||
|
|
||||||
|
The "Corresponding Application Code" for a Combined Work means the
|
||||||
|
object code and/or source code for the Application, including any data
|
||||||
|
and utility programs needed for reproducing the Combined Work from the
|
||||||
|
Application, but excluding the System Libraries of the Combined Work.
|
||||||
|
|
||||||
|
1. Exception to Section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
You may convey a covered work under sections 3 and 4 of this License
|
||||||
|
without being bound by section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
2. Conveying Modified Versions.
|
||||||
|
|
||||||
|
If you modify a copy of the Library, and, in your modifications, a
|
||||||
|
facility refers to a function or data to be supplied by an Application
|
||||||
|
that uses the facility (other than as an argument passed when the
|
||||||
|
facility is invoked), then you may convey a copy of the modified
|
||||||
|
version:
|
||||||
|
|
||||||
|
a) under this License, provided that you make a good faith effort to
|
||||||
|
ensure that, in the event an Application does not supply the
|
||||||
|
function or data, the facility still operates, and performs
|
||||||
|
whatever part of its purpose remains meaningful, or
|
||||||
|
|
||||||
|
b) under the GNU GPL, with none of the additional permissions of
|
||||||
|
this License applicable to that copy.
|
||||||
|
|
||||||
|
3. Object Code Incorporating Material from Library Header Files.
|
||||||
|
|
||||||
|
The object code form of an Application may incorporate material from
|
||||||
|
a header file that is part of the Library. You may convey such object
|
||||||
|
code under terms of your choice, provided that, if the incorporated
|
||||||
|
material is not limited to numerical parameters, data structure
|
||||||
|
layouts and accessors, or small macros, inline functions and templates
|
||||||
|
(ten or fewer lines in length), you do both of the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the object code that the
|
||||||
|
Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
4. Combined Works.
|
||||||
|
|
||||||
|
You may convey a Combined Work under terms of your choice that,
|
||||||
|
taken together, effectively do not restrict modification of the
|
||||||
|
portions of the Library contained in the Combined Work and reverse
|
||||||
|
engineering for debugging such modifications, if you also do each of
|
||||||
|
the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the Combined Work that
|
||||||
|
the Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
c) For a Combined Work that displays copyright notices during
|
||||||
|
execution, include the copyright notice for the Library among
|
||||||
|
these notices, as well as a reference directing the user to the
|
||||||
|
copies of the GNU GPL and this license document.
|
||||||
|
|
||||||
|
d) Do one of the following:
|
||||||
|
|
||||||
|
0) Convey the Minimal Corresponding Source under the terms of this
|
||||||
|
License, and the Corresponding Application Code in a form
|
||||||
|
suitable for, and under terms that permit, the user to
|
||||||
|
recombine or relink the Application with a modified version of
|
||||||
|
the Linked Version to produce a modified Combined Work, in the
|
||||||
|
manner specified by section 6 of the GNU GPL for conveying
|
||||||
|
Corresponding Source.
|
||||||
|
|
||||||
|
1) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (a) uses at run time
|
||||||
|
a copy of the Library already present on the user's computer
|
||||||
|
system, and (b) will operate properly with a modified version of
|
||||||
|
the Library that is interface-compatible with the Linked
|
||||||
|
Version.
|
||||||
|
|
||||||
|
e) Provide Installation Information, but only if you would otherwise
|
||||||
|
be required to provide such information under section 6 of the
|
||||||
|
GNU GPL, and only to the extent that such information is
|
||||||
|
necessary to install and execute a modified version of the
|
||||||
|
Combined Work produced by recombining or relinking the
|
||||||
|
Application with a modified version of the Linked Version. (If
|
||||||
|
you use option 4d0, the Installation Information must accompany
|
||||||
|
the Minimal Corresponding Source and Corresponding Application
|
||||||
|
Code. If you use option 4d1, you must provide the Installation
|
||||||
|
Information in the manner specified by section 6 of the GNU GPL
|
||||||
|
for conveying Corresponding Source.)
|
||||||
|
|
||||||
|
5. Combined Libraries.
|
||||||
|
|
||||||
|
You may place library facilities that are a work based on the
|
||||||
|
Library side by side in a single library together with other library
|
||||||
|
facilities that are not Applications and are not covered by this
|
||||||
|
License, and convey such a combined library under terms of your
|
||||||
|
choice, if you do both of the following:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work based
|
||||||
|
on the Library, uncombined with any other library facilities,
|
||||||
|
conveyed under the terms of this License.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library that part of it
|
||||||
|
is a work based on the Library, and explaining where to find the
|
||||||
|
accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
6. Revised Versions of the GNU Lesser General Public License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the GNU Lesser General Public License from time to time. Such new
|
||||||
|
versions will be similar in spirit to the present version, but may
|
||||||
|
differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Library as you received it specifies that a certain numbered version
|
||||||
|
of the GNU Lesser General Public License "or any later version"
|
||||||
|
applies to it, you have the option of following the terms and
|
||||||
|
conditions either of that published version or of any later version
|
||||||
|
published by the Free Software Foundation. If the Library as you
|
||||||
|
received it does not specify a version number of the GNU Lesser
|
||||||
|
General Public License, you may choose any version of the GNU Lesser
|
||||||
|
General Public License ever published by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Library as you received it specifies that a proxy can decide
|
||||||
|
whether future versions of the GNU Lesser General Public License shall
|
||||||
|
apply, that proxy's public statement of acceptance of any version is
|
||||||
|
permanent authorization for you to choose that version for the
|
||||||
|
Library.
|
||||||
@@ -13,6 +13,8 @@
|
|||||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
<RepositoryUrl>https://github.com/wwiinnddyy/LanMountainDesktop</RepositoryUrl>
|
<RepositoryUrl>https://github.com/wwiinnddyy/LanMountainDesktop</RepositoryUrl>
|
||||||
<RepositoryType>git</RepositoryType>
|
<RepositoryType>git</RepositoryType>
|
||||||
|
<PackageLicenseExpression>LGPL-3.0-or-later</PackageLicenseExpression>
|
||||||
|
<Copyright>Copyright (c) LanMountainDesktop Contributors</Copyright>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
165
LanMountainDesktop.Shared.Contracts/LICENSE
Normal file
165
LanMountainDesktop.Shared.Contracts/LICENSE
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|
||||||
|
This version of the GNU Lesser General Public License incorporates
|
||||||
|
the terms and conditions of version 3 of the GNU General Public
|
||||||
|
License, supplemented by the additional permissions listed below.
|
||||||
|
|
||||||
|
0. Additional Definitions.
|
||||||
|
|
||||||
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
|
General Public License.
|
||||||
|
|
||||||
|
"The Library" refers to a covered work governed by this License,
|
||||||
|
other than an Application or a Combined Work as defined below.
|
||||||
|
|
||||||
|
An "Application" is any work that makes use of an interface provided
|
||||||
|
by the Library, but which is not otherwise based on the Library.
|
||||||
|
Defining a subclass of a class defined by the Library is deemed a mode
|
||||||
|
of using an interface provided by the Library.
|
||||||
|
|
||||||
|
A "Combined Work" is a work produced by combining or linking an
|
||||||
|
Application with the Library. The particular version of the Library
|
||||||
|
with which the Combined Work was made is also called the "Linked
|
||||||
|
Version".
|
||||||
|
|
||||||
|
The "Minimal Corresponding Source" for a Combined Work means the
|
||||||
|
Corresponding Source for the Combined Work, excluding any source code
|
||||||
|
for portions of the Combined Work that, considered in isolation, are
|
||||||
|
based on the Application, and not on the Linked Version.
|
||||||
|
|
||||||
|
The "Corresponding Application Code" for a Combined Work means the
|
||||||
|
object code and/or source code for the Application, including any data
|
||||||
|
and utility programs needed for reproducing the Combined Work from the
|
||||||
|
Application, but excluding the System Libraries of the Combined Work.
|
||||||
|
|
||||||
|
1. Exception to Section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
You may convey a covered work under sections 3 and 4 of this License
|
||||||
|
without being bound by section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
2. Conveying Modified Versions.
|
||||||
|
|
||||||
|
If you modify a copy of the Library, and, in your modifications, a
|
||||||
|
facility refers to a function or data to be supplied by an Application
|
||||||
|
that uses the facility (other than as an argument passed when the
|
||||||
|
facility is invoked), then you may convey a copy of the modified
|
||||||
|
version:
|
||||||
|
|
||||||
|
a) under this License, provided that you make a good faith effort to
|
||||||
|
ensure that, in the event an Application does not supply the
|
||||||
|
function or data, the facility still operates, and performs
|
||||||
|
whatever part of its purpose remains meaningful, or
|
||||||
|
|
||||||
|
b) under the GNU GPL, with none of the additional permissions of
|
||||||
|
this License applicable to that copy.
|
||||||
|
|
||||||
|
3. Object Code Incorporating Material from Library Header Files.
|
||||||
|
|
||||||
|
The object code form of an Application may incorporate material from
|
||||||
|
a header file that is part of the Library. You may convey such object
|
||||||
|
code under terms of your choice, provided that, if the incorporated
|
||||||
|
material is not limited to numerical parameters, data structure
|
||||||
|
layouts and accessors, or small macros, inline functions and templates
|
||||||
|
(ten or fewer lines in length), you do both of the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the object code that the
|
||||||
|
Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
4. Combined Works.
|
||||||
|
|
||||||
|
You may convey a Combined Work under terms of your choice that,
|
||||||
|
taken together, effectively do not restrict modification of the
|
||||||
|
portions of the Library contained in the Combined Work and reverse
|
||||||
|
engineering for debugging such modifications, if you also do each of
|
||||||
|
the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the Combined Work that
|
||||||
|
the Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
c) For a Combined Work that displays copyright notices during
|
||||||
|
execution, include the copyright notice for the Library among
|
||||||
|
these notices, as well as a reference directing the user to the
|
||||||
|
copies of the GNU GPL and this license document.
|
||||||
|
|
||||||
|
d) Do one of the following:
|
||||||
|
|
||||||
|
0) Convey the Minimal Corresponding Source under the terms of this
|
||||||
|
License, and the Corresponding Application Code in a form
|
||||||
|
suitable for, and under terms that permit, the user to
|
||||||
|
recombine or relink the Application with a modified version of
|
||||||
|
the Linked Version to produce a modified Combined Work, in the
|
||||||
|
manner specified by section 6 of the GNU GPL for conveying
|
||||||
|
Corresponding Source.
|
||||||
|
|
||||||
|
1) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (a) uses at run time
|
||||||
|
a copy of the Library already present on the user's computer
|
||||||
|
system, and (b) will operate properly with a modified version of
|
||||||
|
the Library that is interface-compatible with the Linked
|
||||||
|
Version.
|
||||||
|
|
||||||
|
e) Provide Installation Information, but only if you would otherwise
|
||||||
|
be required to provide such information under section 6 of the
|
||||||
|
GNU GPL, and only to the extent that such information is
|
||||||
|
necessary to install and execute a modified version of the
|
||||||
|
Combined Work produced by recombining or relinking the
|
||||||
|
Application with a modified version of the Linked Version. (If
|
||||||
|
you use option 4d0, the Installation Information must accompany
|
||||||
|
the Minimal Corresponding Source and Corresponding Application
|
||||||
|
Code. If you use option 4d1, you must provide the Installation
|
||||||
|
Information in the manner specified by section 6 of the GNU GPL
|
||||||
|
for conveying Corresponding Source.)
|
||||||
|
|
||||||
|
5. Combined Libraries.
|
||||||
|
|
||||||
|
You may place library facilities that are a work based on the
|
||||||
|
Library side by side in a single library together with other library
|
||||||
|
facilities that are not Applications and are not covered by this
|
||||||
|
License, and convey such a combined library under terms of your
|
||||||
|
choice, if you do both of the following:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work based
|
||||||
|
on the Library, uncombined with any other library facilities,
|
||||||
|
conveyed under the terms of this License.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library that part of it
|
||||||
|
is a work based on the Library, and explaining where to find the
|
||||||
|
accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
6. Revised Versions of the GNU Lesser General Public License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the GNU Lesser General Public License from time to time. Such new
|
||||||
|
versions will be similar in spirit to the present version, but may
|
||||||
|
differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Library as you received it specifies that a certain numbered version
|
||||||
|
of the GNU Lesser General Public License "or any later version"
|
||||||
|
applies to it, you have the option of following the terms and
|
||||||
|
conditions either of that published version or of any later version
|
||||||
|
published by the Free Software Foundation. If the Library as you
|
||||||
|
received it does not specify a version number of the GNU Lesser
|
||||||
|
General Public License, you may choose any version of the GNU Lesser
|
||||||
|
General Public License ever published by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Library as you received it specifies that a proxy can decide
|
||||||
|
whether future versions of the GNU Lesser General Public License shall
|
||||||
|
apply, that proxy's public statement of acceptance of any version is
|
||||||
|
permanent authorization for you to choose that version for the
|
||||||
|
Library.
|
||||||
@@ -13,6 +13,8 @@
|
|||||||
<RepositoryUrl>https://github.com/wwiinnddyy/LanMountainDesktop</RepositoryUrl>
|
<RepositoryUrl>https://github.com/wwiinnddyy/LanMountainDesktop</RepositoryUrl>
|
||||||
<RepositoryType>git</RepositoryType>
|
<RepositoryType>git</RepositoryType>
|
||||||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
||||||
|
<PackageLicenseExpression>LGPL-3.0-or-later</PackageLicenseExpression>
|
||||||
|
<Copyright>Copyright (c) LanMountainDesktop Contributors</Copyright>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Avalonia" Version="11.3.12" />
|
<PackageReference Include="Avalonia" Version="11.3.12" />
|
||||||
|
|||||||
@@ -1087,5 +1087,23 @@
|
|||||||
"zhijiaohub.settings.auto_refresh_desc": "Automatically refresh the image list periodically.",
|
"zhijiaohub.settings.auto_refresh_desc": "Automatically refresh the image list periodically.",
|
||||||
"zhijiaohub.settings.interval": "Refresh Interval (minutes)",
|
"zhijiaohub.settings.interval": "Refresh Interval (minutes)",
|
||||||
"zhijiaohub.settings.about": "About",
|
"zhijiaohub.settings.about": "About",
|
||||||
"zhijiaohub.settings.about_desc": "ZhiJiaoHub displays interesting images from the educational technology community. Images are fetched from GitHub repositories and cached locally."
|
"zhijiaohub.settings.about_desc": "ZhiJiaoHub displays interesting images from the educational technology community. Images are fetched from GitHub repositories and cached locally.",
|
||||||
|
"power.menu": "Power",
|
||||||
|
"power.title": "Power",
|
||||||
|
"power.back": "Back",
|
||||||
|
"power.shutdown": "Shutdown",
|
||||||
|
"power.restart": "Restart",
|
||||||
|
"power.logout": "Log Out",
|
||||||
|
"power.sleep": "Sleep",
|
||||||
|
"power.lock_screen": "Lock Screen",
|
||||||
|
"power.shutdown_confirm_title": "Shutdown Confirmation",
|
||||||
|
"power.shutdown_confirm_message": "Are you sure you want to shut down this computer? Unsaved data may be lost.",
|
||||||
|
"power.restart_confirm_title": "Restart Confirmation",
|
||||||
|
"power.restart_confirm_message": "Are you sure you want to restart this computer? Unsaved data may be lost.",
|
||||||
|
"power.logout_confirm_title": "Log Out Confirmation",
|
||||||
|
"power.logout_confirm_message": "Are you sure you want to log out?",
|
||||||
|
"power.sleep_confirm_title": "Sleep Confirmation",
|
||||||
|
"power.sleep_confirm_message": "Are you sure you want to put the computer to sleep?",
|
||||||
|
"power.confirm_yes": "Yes",
|
||||||
|
"power.confirm_cancel": "Cancel"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1081,5 +1081,23 @@
|
|||||||
"zhijiaohub.settings.auto_refresh_desc": "定期自动刷新图片列表。",
|
"zhijiaohub.settings.auto_refresh_desc": "定期自动刷新图片列表。",
|
||||||
"zhijiaohub.settings.interval": "刷新间隔(分钟)",
|
"zhijiaohub.settings.interval": "刷新间隔(分钟)",
|
||||||
"zhijiaohub.settings.about": "关于",
|
"zhijiaohub.settings.about": "关于",
|
||||||
"zhijiaohub.settings.about_desc": "智教Hub 展示来自教育技术社区的有趣图片。图片从 GitHub 仓库获取并缓存在本地。"
|
"zhijiaohub.settings.about_desc": "智教Hub 展示来自教育技术社区的有趣图片。图片从 GitHub 仓库获取并缓存在本地。",
|
||||||
|
"power.menu": "电源",
|
||||||
|
"power.title": "电源",
|
||||||
|
"power.back": "返回",
|
||||||
|
"power.shutdown": "关机",
|
||||||
|
"power.restart": "重启",
|
||||||
|
"power.logout": "注销",
|
||||||
|
"power.sleep": "睡眠",
|
||||||
|
"power.lock_screen": "锁定屏幕",
|
||||||
|
"power.shutdown_confirm_title": "关机确认",
|
||||||
|
"power.shutdown_confirm_message": "确定要关闭计算机吗?未保存的数据可能会丢失。",
|
||||||
|
"power.restart_confirm_title": "重启确认",
|
||||||
|
"power.restart_confirm_message": "确定要重启计算机吗?未保存的数据可能会丢失。",
|
||||||
|
"power.logout_confirm_title": "注销确认",
|
||||||
|
"power.logout_confirm_message": "确定要注销当前用户吗?",
|
||||||
|
"power.sleep_confirm_title": "睡眠确认",
|
||||||
|
"power.sleep_confirm_message": "确定要让计算机进入睡眠状态吗?",
|
||||||
|
"power.confirm_yes": "确定",
|
||||||
|
"power.confirm_cancel": "取消"
|
||||||
}
|
}
|
||||||
|
|||||||
253
LanMountainDesktop/Services/PowerManagementService.cs
Normal file
253
LanMountainDesktop/Services/PowerManagementService.cs
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace LanMountainDesktop.Services;
|
||||||
|
|
||||||
|
public interface IPowerManagementService
|
||||||
|
{
|
||||||
|
bool IsShutdownSupported { get; }
|
||||||
|
bool IsRestartSupported { get; }
|
||||||
|
bool IsLogoutSupported { get; }
|
||||||
|
bool IsLockSupported { get; }
|
||||||
|
bool IsSleepSupported { get; }
|
||||||
|
|
||||||
|
Task ShutdownAsync();
|
||||||
|
Task RestartAsync();
|
||||||
|
Task LogoutAsync();
|
||||||
|
Task LockAsync();
|
||||||
|
Task SleepAsync();
|
||||||
|
|
||||||
|
void ShowNativePowerUI(PowerAction action);
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum PowerAction
|
||||||
|
{
|
||||||
|
Shutdown,
|
||||||
|
Restart
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PowerManagementServiceFactory
|
||||||
|
{
|
||||||
|
private static IPowerManagementService? _instance;
|
||||||
|
private static readonly object _lock = new();
|
||||||
|
|
||||||
|
public static IPowerManagementService GetOrCreate()
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
return _instance ??= CreatePlatformService();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IPowerManagementService CreatePlatformService()
|
||||||
|
{
|
||||||
|
if (OperatingSystem.IsWindows())
|
||||||
|
return new WindowsPowerManagementService();
|
||||||
|
if (OperatingSystem.IsLinux())
|
||||||
|
return new LinuxPowerManagementService();
|
||||||
|
return new NullPowerManagementService();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class WindowsPowerManagementService : IPowerManagementService
|
||||||
|
{
|
||||||
|
public bool IsShutdownSupported => true;
|
||||||
|
public bool IsRestartSupported => true;
|
||||||
|
public bool IsLogoutSupported => true;
|
||||||
|
public bool IsLockSupported => true;
|
||||||
|
public bool IsSleepSupported => true;
|
||||||
|
|
||||||
|
public async Task ShutdownAsync()
|
||||||
|
{
|
||||||
|
await Task.Run(() =>
|
||||||
|
{
|
||||||
|
Process.Start(new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = "shutdown",
|
||||||
|
Arguments = "/s /t 0",
|
||||||
|
UseShellExecute = true,
|
||||||
|
WindowStyle = ProcessWindowStyle.Hidden
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RestartAsync()
|
||||||
|
{
|
||||||
|
await Task.Run(() =>
|
||||||
|
{
|
||||||
|
Process.Start(new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = "shutdown",
|
||||||
|
Arguments = "/r /t 0",
|
||||||
|
UseShellExecute = true,
|
||||||
|
WindowStyle = ProcessWindowStyle.Hidden
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task LogoutAsync()
|
||||||
|
{
|
||||||
|
await Task.Run(() =>
|
||||||
|
{
|
||||||
|
ExitWindowsEx(0, 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task LockAsync()
|
||||||
|
{
|
||||||
|
await Task.Run(() =>
|
||||||
|
{
|
||||||
|
LockWorkStation();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SleepAsync()
|
||||||
|
{
|
||||||
|
await Task.Run(() =>
|
||||||
|
{
|
||||||
|
SetSuspendState(false, false, false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowNativePowerUI(PowerAction action)
|
||||||
|
{
|
||||||
|
var slideToShutDownPath = Environment.ExpandEnvironmentVariables(@"%windir%\System32\SlideToShutDown.exe");
|
||||||
|
if (System.IO.File.Exists(slideToShutDownPath))
|
||||||
|
{
|
||||||
|
Process.Start(new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = slideToShutDownPath,
|
||||||
|
UseShellExecute = true
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case PowerAction.Shutdown:
|
||||||
|
Process.Start(new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = "shutdown",
|
||||||
|
Arguments = "/s /t 5 /c \"LanMountainDesktop: Shutting down...\"",
|
||||||
|
UseShellExecute = true
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PowerAction.Restart:
|
||||||
|
Process.Start(new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = "shutdown",
|
||||||
|
Arguments = "/r /t 5 /c \"LanMountainDesktop: Restarting...\"",
|
||||||
|
UseShellExecute = true
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("user32.dll", SetLastError = true)]
|
||||||
|
private static extern bool ExitWindowsEx(uint uFlags, uint dwReason);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
private static extern void LockWorkStation();
|
||||||
|
|
||||||
|
[DllImport("powrprof.dll", SetLastError = true)]
|
||||||
|
private static extern bool SetSuspendState(bool hibernate, bool forceCritical, bool disableWakeEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class LinuxPowerManagementService : IPowerManagementService
|
||||||
|
{
|
||||||
|
public bool IsShutdownSupported => true;
|
||||||
|
public bool IsRestartSupported => true;
|
||||||
|
public bool IsLogoutSupported => true;
|
||||||
|
public bool IsLockSupported => true;
|
||||||
|
public bool IsSleepSupported => true;
|
||||||
|
|
||||||
|
public async Task ShutdownAsync()
|
||||||
|
{
|
||||||
|
await RunSystemctlCommand("poweroff -i");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RestartAsync()
|
||||||
|
{
|
||||||
|
await RunSystemctlCommand("reboot -i");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task LogoutAsync()
|
||||||
|
{
|
||||||
|
await RunLoginctlCommand("terminate-session $XDG_SESSION_ID");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task LockAsync()
|
||||||
|
{
|
||||||
|
await RunLoginctlCommand("lock-session");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SleepAsync()
|
||||||
|
{
|
||||||
|
await RunSystemctlCommand("suspend -i");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowNativePowerUI(PowerAction action)
|
||||||
|
{
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case PowerAction.Shutdown:
|
||||||
|
RunProcess("systemctl", "poweroff -i");
|
||||||
|
break;
|
||||||
|
case PowerAction.Restart:
|
||||||
|
RunProcess("systemctl", "reboot -i");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task RunSystemctlCommand(string args)
|
||||||
|
{
|
||||||
|
await RunProcess("systemctl", args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task RunLoginctlCommand(string args)
|
||||||
|
{
|
||||||
|
await RunProcess("loginctl", args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task RunProcess(string command, string args)
|
||||||
|
{
|
||||||
|
await Task.Run(() =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Process.Start(new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = command,
|
||||||
|
Arguments = args,
|
||||||
|
UseShellExecute = false,
|
||||||
|
RedirectStandardError = true,
|
||||||
|
CreateNoWindow = true
|
||||||
|
})?.WaitForExit(5000);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
AppLogger.Error("LinuxPowerManagement", $"Failed to execute {command} {args}: {ex.Message}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class NullPowerManagementService : IPowerManagementService
|
||||||
|
{
|
||||||
|
public bool IsShutdownSupported => false;
|
||||||
|
public bool IsRestartSupported => false;
|
||||||
|
public bool IsLogoutSupported => false;
|
||||||
|
public bool IsLockSupported => false;
|
||||||
|
public bool IsSleepSupported => false;
|
||||||
|
|
||||||
|
public Task ShutdownAsync() => Task.CompletedTask;
|
||||||
|
public Task RestartAsync() => Task.CompletedTask;
|
||||||
|
public Task LogoutAsync() => Task.CompletedTask;
|
||||||
|
public Task LockAsync() => Task.CompletedTask;
|
||||||
|
public Task SleepAsync() => Task.CompletedTask;
|
||||||
|
|
||||||
|
public void ShowNativePowerUI(PowerAction action) { }
|
||||||
|
}
|
||||||
@@ -74,6 +74,10 @@ public partial class MainWindow
|
|||||||
Color PressedColor,
|
Color PressedColor,
|
||||||
Color DividerColor);
|
Color DividerColor);
|
||||||
|
|
||||||
|
private readonly IPowerManagementService _powerService = PowerManagementServiceFactory.GetOrCreate();
|
||||||
|
private bool _isPowerMenuOpen;
|
||||||
|
private bool _isPowerMenuAnimating;
|
||||||
|
|
||||||
private void InitializeTaskbarProfileFlyout()
|
private void InitializeTaskbarProfileFlyout()
|
||||||
{
|
{
|
||||||
if (TaskbarProfileButton is null || TaskbarProfilePopup is null)
|
if (TaskbarProfileButton is null || TaskbarProfilePopup is null)
|
||||||
@@ -98,6 +102,16 @@ public partial class MainWindow
|
|||||||
TaskbarProfileDisplayNameTextBlock.Text = profile.DisplayName;
|
TaskbarProfileDisplayNameTextBlock.Text = profile.DisplayName;
|
||||||
TaskbarProfileSettingsActionTextBlock.Text = L("tooltip.open_settings", "Settings");
|
TaskbarProfileSettingsActionTextBlock.Text = L("tooltip.open_settings", "Settings");
|
||||||
TaskbarProfileDesktopEditActionTextBlock.Text = L("button.component_library", "Edit Desktop");
|
TaskbarProfileDesktopEditActionTextBlock.Text = L("button.component_library", "Edit Desktop");
|
||||||
|
TaskbarProfilePowerActionTextBlock.Text = L("power.menu", "Power");
|
||||||
|
TaskbarPowerTitleTextBlock.Text = L("power.title", "Power");
|
||||||
|
TaskbarPowerBackTextBlock.Text = L("power.back", "Back");
|
||||||
|
PowerShutdownTextBlock.Text = L("power.shutdown", "Shutdown");
|
||||||
|
PowerRestartTextBlock.Text = L("power.restart", "Restart");
|
||||||
|
PowerLogoutTextBlock.Text = L("power.logout", "Log Out");
|
||||||
|
PowerSleepTextBlock.Text = L("power.sleep", "Sleep");
|
||||||
|
PowerLockTextBlock.Text = L("power.lock_screen", "Lock Screen");
|
||||||
|
|
||||||
|
UpdatePowerMenuVisibility();
|
||||||
ApplyTaskbarProfilePopupTheme(_appearanceThemeService.GetCurrent());
|
ApplyTaskbarProfilePopupTheme(_appearanceThemeService.GetCurrent());
|
||||||
|
|
||||||
ToolTip.SetTip(TaskbarProfileButton, profile.DisplayName);
|
ToolTip.SetTip(TaskbarProfileButton, profile.DisplayName);
|
||||||
@@ -216,6 +230,7 @@ public partial class MainWindow
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResetPowerMenuState();
|
||||||
RefreshTaskbarProfilePresentation();
|
RefreshTaskbarProfilePresentation();
|
||||||
TaskbarProfilePopup.IsOpen = true;
|
TaskbarProfilePopup.IsOpen = true;
|
||||||
}
|
}
|
||||||
@@ -279,6 +294,202 @@ public partial class MainWindow
|
|||||||
app?.OpenIndependentSettingsModule("MainWindowTaskbar");
|
app?.OpenIndependentSettingsModule("MainWindowTaskbar");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnPowerMenuEnterClick(object? sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
_ = sender;
|
||||||
|
_ = e;
|
||||||
|
EnterPowerMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPowerMenuBackClick(object? sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
_ = sender;
|
||||||
|
_ = e;
|
||||||
|
ExitPowerMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResetPowerMenuState()
|
||||||
|
{
|
||||||
|
_isPowerMenuOpen = false;
|
||||||
|
_isPowerMenuAnimating = false;
|
||||||
|
|
||||||
|
if (TaskbarProfileMainPanel is not null)
|
||||||
|
{
|
||||||
|
TaskbarProfileMainPanel.IsVisible = true;
|
||||||
|
TaskbarProfileMainPanel.Opacity = 1d;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TaskbarProfilePowerPanel is not null)
|
||||||
|
{
|
||||||
|
TaskbarProfilePowerPanel.IsVisible = false;
|
||||||
|
TaskbarProfilePowerPanel.Opacity = 0d;
|
||||||
|
var transform = TaskbarProfilePowerPanel.RenderTransform as TranslateTransform;
|
||||||
|
if (transform is not null) transform.X = 340d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdatePowerMenuVisibility()
|
||||||
|
{
|
||||||
|
var supported = _powerService.IsShutdownSupported ||
|
||||||
|
_powerService.IsRestartSupported ||
|
||||||
|
_powerService.IsLogoutSupported ||
|
||||||
|
_powerService.IsSleepSupported ||
|
||||||
|
_powerService.IsLockSupported;
|
||||||
|
|
||||||
|
if (TaskbarProfilePowerActionButton is not null)
|
||||||
|
{
|
||||||
|
TaskbarProfilePowerActionButton.IsVisible = supported;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void EnterPowerMenu()
|
||||||
|
{
|
||||||
|
if (_isPowerMenuAnimating || _isPowerMenuOpen || TaskbarProfileMainPanel is null || TaskbarProfilePowerPanel is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_isPowerMenuAnimating = true;
|
||||||
|
|
||||||
|
TaskbarProfilePowerPanel.IsVisible = true;
|
||||||
|
TaskbarProfilePowerPanel.Opacity = 0d;
|
||||||
|
var powerTransform = TaskbarProfilePowerPanel.RenderTransform as TranslateTransform;
|
||||||
|
if (powerTransform is not null) powerTransform.X = 340d;
|
||||||
|
|
||||||
|
await Task.Delay(16);
|
||||||
|
|
||||||
|
TaskbarProfileMainPanel.Opacity = 0d;
|
||||||
|
TaskbarProfilePowerPanel.Opacity = 1d;
|
||||||
|
if (powerTransform is not null) powerTransform.X = 0d;
|
||||||
|
|
||||||
|
await Task.Delay(280);
|
||||||
|
|
||||||
|
TaskbarProfileMainPanel.IsVisible = false;
|
||||||
|
_isPowerMenuOpen = true;
|
||||||
|
_isPowerMenuAnimating = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void ExitPowerMenu()
|
||||||
|
{
|
||||||
|
if (_isPowerMenuAnimating || !_isPowerMenuOpen || TaskbarProfileMainPanel is null || TaskbarProfilePowerPanel is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_isPowerMenuAnimating = true;
|
||||||
|
|
||||||
|
TaskbarProfileMainPanel.IsVisible = true;
|
||||||
|
TaskbarProfileMainPanel.Opacity = 0d;
|
||||||
|
var powerTransform = TaskbarProfilePowerPanel.RenderTransform as TranslateTransform;
|
||||||
|
if (powerTransform is not null) powerTransform.X = 0d;
|
||||||
|
|
||||||
|
await Task.Delay(16);
|
||||||
|
|
||||||
|
TaskbarProfileMainPanel.Opacity = 1d;
|
||||||
|
TaskbarProfilePowerPanel.Opacity = 0d;
|
||||||
|
if (powerTransform is not null) powerTransform.X = 340d;
|
||||||
|
|
||||||
|
await Task.Delay(280);
|
||||||
|
|
||||||
|
TaskbarProfilePowerPanel.IsVisible = false;
|
||||||
|
_isPowerMenuOpen = false;
|
||||||
|
_isPowerMenuAnimating = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void OnPowerShutdownClick(object? sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
_ = sender;
|
||||||
|
_ = e;
|
||||||
|
ClosePopupIfOpen();
|
||||||
|
|
||||||
|
if (OperatingSystem.IsWindows())
|
||||||
|
{
|
||||||
|
_powerService.ShowNativePowerUI(PowerAction.Shutdown);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await ShowPowerConfirmDialogAsync(L("power.shutdown_confirm_title", "Shutdown"),
|
||||||
|
L("power.shutdown_confirm_message", "Are you sure you want to shut down this computer?"),
|
||||||
|
() => _powerService.ShutdownAsync());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void OnPowerRestartClick(object? sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
_ = sender;
|
||||||
|
_ = e;
|
||||||
|
ClosePopupIfOpen();
|
||||||
|
|
||||||
|
if (OperatingSystem.IsWindows())
|
||||||
|
{
|
||||||
|
_powerService.ShowNativePowerUI(PowerAction.Restart);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await ShowPowerConfirmDialogAsync(L("power.restart_confirm_title", "Restart"),
|
||||||
|
L("power.restart_confirm_message", "Are you sure you want to restart this computer?"),
|
||||||
|
() => _powerService.RestartAsync());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void OnPowerLogoutClick(object? sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
_ = sender;
|
||||||
|
_ = e;
|
||||||
|
ClosePopupIfOpen();
|
||||||
|
|
||||||
|
await ShowPowerConfirmDialogAsync(L("power.logout_confirm_title", "Log Out"),
|
||||||
|
L("power.logout_confirm_message", "Are you sure you want to log out?"),
|
||||||
|
() => _powerService.LogoutAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void OnPowerSleepClick(object? sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
_ = sender;
|
||||||
|
_ = e;
|
||||||
|
ClosePopupIfOpen();
|
||||||
|
|
||||||
|
await ShowPowerConfirmDialogAsync(L("power.sleep_confirm_title", "Sleep"),
|
||||||
|
L("power.sleep_confirm_message", "Are you sure you want to put the computer to sleep?"),
|
||||||
|
() => _powerService.SleepAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void OnPowerLockClick(object? sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
_ = sender;
|
||||||
|
_ = e;
|
||||||
|
ClosePopupIfOpen();
|
||||||
|
await _powerService.LockAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ShowPowerConfirmDialogAsync(string title, string message, Func<Task> action)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var dialog = new ContentDialog
|
||||||
|
{
|
||||||
|
Title = title,
|
||||||
|
Content = message,
|
||||||
|
PrimaryButtonText = L("power.confirm_yes", "Yes"),
|
||||||
|
SecondaryButtonText = L("power.confirm_cancel", "Cancel")
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = await dialog.ShowAsync(this);
|
||||||
|
if (result == ContentDialogResult.Primary)
|
||||||
|
{
|
||||||
|
await action();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
AppLogger.Error("PowerMenu", $"Dialog error: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClosePopupIfOpen()
|
||||||
|
{
|
||||||
|
if (TaskbarProfilePopup is not null && TaskbarProfilePopup.IsOpen)
|
||||||
|
{
|
||||||
|
TaskbarProfilePopup.IsOpen = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void OnCloseComponentLibraryClick(object? sender, RoutedEventArgs e)
|
private void OnCloseComponentLibraryClick(object? sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
_componentLibraryWindowService.Close(this);
|
_componentLibraryWindowService.Close(this);
|
||||||
|
|||||||
@@ -398,8 +398,16 @@
|
|||||||
<Border x:Name="TaskbarProfilePopupPanel"
|
<Border x:Name="TaskbarProfilePopupPanel"
|
||||||
Classes="taskbar-profile-popup-panel"
|
Classes="taskbar-profile-popup-panel"
|
||||||
Margin="0,0,0,10">
|
Margin="0,0,0,10">
|
||||||
<StackPanel Width="280"
|
<Grid Width="340">
|
||||||
Spacing="12">
|
<Grid x:Name="TaskbarProfileMainPanel"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
VerticalAlignment="Stretch">
|
||||||
|
<Grid.Transitions>
|
||||||
|
<Transitions>
|
||||||
|
<DoubleTransition Property="Opacity" Duration="{StaticResource FluttermotionToken.Duration.Fast}" />
|
||||||
|
</Transitions>
|
||||||
|
</Grid.Transitions>
|
||||||
|
<StackPanel Spacing="12">
|
||||||
<Grid ColumnDefinitions="Auto,*"
|
<Grid ColumnDefinitions="Auto,*"
|
||||||
ColumnSpacing="12">
|
ColumnSpacing="12">
|
||||||
<Border x:Name="TaskbarProfileHeaderAvatarBorder"
|
<Border x:Name="TaskbarProfileHeaderAvatarBorder"
|
||||||
@@ -460,7 +468,145 @@
|
|||||||
Text="Edit Desktop" />
|
Text="Edit Desktop" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
<Button x:Name="TaskbarProfilePowerActionButton"
|
||||||
|
Classes="taskbar-profile-popup-action"
|
||||||
|
Click="OnPowerMenuEnterClick">
|
||||||
|
<Grid ColumnDefinitions="Auto,*"
|
||||||
|
ColumnSpacing="12">
|
||||||
|
<mi:MaterialIcon Classes="taskbar-profile-popup-action-icon"
|
||||||
|
Kind="Power" />
|
||||||
|
<TextBlock x:Name="TaskbarProfilePowerActionTextBlock"
|
||||||
|
Grid.Column="1"
|
||||||
|
Classes="taskbar-profile-popup-action-text"
|
||||||
|
Text="Power" />
|
||||||
|
</Grid>
|
||||||
|
</Button>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid x:Name="TaskbarProfilePowerPanel"
|
||||||
|
IsVisible="False"
|
||||||
|
Opacity="0"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
VerticalAlignment="Stretch">
|
||||||
|
<Grid.Transitions>
|
||||||
|
<Transitions>
|
||||||
|
<DoubleTransition Property="Opacity" Duration="{StaticResource FluttermotionToken.Duration.Fast}" />
|
||||||
|
</Transitions>
|
||||||
|
</Grid.Transitions>
|
||||||
|
<Grid.RenderTransform>
|
||||||
|
<TranslateTransform>
|
||||||
|
<TranslateTransform.Transitions>
|
||||||
|
<Transitions>
|
||||||
|
<DoubleTransition Property="X"
|
||||||
|
Duration="{StaticResource FluttermotionToken.Duration.Fast}"
|
||||||
|
Easing="0.22,1,0.36,1" />
|
||||||
|
</Transitions>
|
||||||
|
</TranslateTransform.Transitions>
|
||||||
|
</TranslateTransform>
|
||||||
|
</Grid.RenderTransform>
|
||||||
|
<StackPanel Spacing="8">
|
||||||
|
<Button x:Name="TaskbarPowerBackButton"
|
||||||
|
Padding="4,6"
|
||||||
|
Background="Transparent"
|
||||||
|
BorderThickness="0"
|
||||||
|
Foreground="{DynamicResource AdaptiveTextPrimaryBrush}"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Click="OnPowerMenuBackClick">
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||||
|
<fi:SymbolIcon Classes="icon-s"
|
||||||
|
Symbol="ArrowLeft"
|
||||||
|
IconVariant="Regular" />
|
||||||
|
<TextBlock x:Name="TaskbarPowerBackTextBlock"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Text="Back" />
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<TextBlock x:Name="TaskbarPowerTitleTextBlock"
|
||||||
|
FontSize="16"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
Foreground="{DynamicResource TaskbarProfilePopupTextBrush}"
|
||||||
|
Margin="2,6,0,0"
|
||||||
|
Text="Power" />
|
||||||
|
|
||||||
|
<Border Height="1"
|
||||||
|
Background="{DynamicResource TaskbarProfilePopupDividerBrush}"
|
||||||
|
Margin="0,4" />
|
||||||
|
|
||||||
|
<Button x:Name="PowerShutdownButton"
|
||||||
|
Classes="taskbar-profile-popup-action"
|
||||||
|
Click="OnPowerShutdownClick">
|
||||||
|
<Grid ColumnDefinitions="Auto,*"
|
||||||
|
ColumnSpacing="14">
|
||||||
|
<mi:MaterialIcon Classes="taskbar-profile-popup-action-icon"
|
||||||
|
Kind="Power" />
|
||||||
|
<TextBlock x:Name="PowerShutdownTextBlock"
|
||||||
|
Grid.Column="1"
|
||||||
|
Classes="taskbar-profile-popup-action-text"
|
||||||
|
Text="Shutdown" />
|
||||||
|
</Grid>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button x:Name="PowerRestartButton"
|
||||||
|
Classes="taskbar-profile-popup-action"
|
||||||
|
Click="OnPowerRestartClick">
|
||||||
|
<Grid ColumnDefinitions="Auto,*"
|
||||||
|
ColumnSpacing="14">
|
||||||
|
<mi:MaterialIcon Classes="taskbar-profile-popup-action-icon"
|
||||||
|
Kind="Refresh" />
|
||||||
|
<TextBlock x:Name="PowerRestartTextBlock"
|
||||||
|
Grid.Column="1"
|
||||||
|
Classes="taskbar-profile-popup-action-text"
|
||||||
|
Text="Restart" />
|
||||||
|
</Grid>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button x:Name="PowerLogoutButton"
|
||||||
|
Classes="taskbar-profile-popup-action"
|
||||||
|
Click="OnPowerLogoutClick">
|
||||||
|
<Grid ColumnDefinitions="Auto,*"
|
||||||
|
ColumnSpacing="14">
|
||||||
|
<mi:MaterialIcon Classes="taskbar-profile-popup-action-icon"
|
||||||
|
Kind="ExitToApp" />
|
||||||
|
<TextBlock x:Name="PowerLogoutTextBlock"
|
||||||
|
Grid.Column="1"
|
||||||
|
Classes="taskbar-profile-popup-action-text"
|
||||||
|
Text="Log Out" />
|
||||||
|
</Grid>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button x:Name="PowerSleepButton"
|
||||||
|
Classes="taskbar-profile-popup-action"
|
||||||
|
Click="OnPowerSleepClick">
|
||||||
|
<Grid ColumnDefinitions="Auto,*"
|
||||||
|
ColumnSpacing="14">
|
||||||
|
<mi:MaterialIcon Classes="taskbar-profile-popup-action-icon"
|
||||||
|
Kind="WeatherNight" />
|
||||||
|
<TextBlock x:Name="PowerSleepTextBlock"
|
||||||
|
Grid.Column="1"
|
||||||
|
Classes="taskbar-profile-popup-action-text"
|
||||||
|
Text="Sleep" />
|
||||||
|
</Grid>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button x:Name="PowerLockButton"
|
||||||
|
Classes="taskbar-profile-popup-action"
|
||||||
|
Click="OnPowerLockClick">
|
||||||
|
<Grid ColumnDefinitions="Auto,*"
|
||||||
|
ColumnSpacing="14">
|
||||||
|
<mi:MaterialIcon Classes="taskbar-profile-popup-action-icon"
|
||||||
|
Kind="Lock" />
|
||||||
|
<TextBlock x:Name="PowerLockTextBlock"
|
||||||
|
Grid.Column="1"
|
||||||
|
Classes="taskbar-profile-popup-action-text"
|
||||||
|
Text="Lock Screen" />
|
||||||
|
</Grid>
|
||||||
|
</Button>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
</Popup>
|
</Popup>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
Reference in New Issue
Block a user