跳到主要内容

github/tai

公开

Tai · Windows 软件与网站使用时长统计。上游 Planshit/Tai 的源码镜像,非灵栈原创;MIT 许可。来源:https://github.com/Planshit/Tai 。本次为手动同步,暂不提供安装包。

提交记录
修改Core/App.config+13 −13看文件
@@ -1,35 +1,35 @@
1删除:<?xml version="1.0" encoding="utf-8"?>
1新增:<?xml version="1.0" encoding="utf-8"?>
22<configuration>
33 <configSections>
44 <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
5删除: <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
5新增: <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
66 </configSections>
77 <entityFramework>
88 <providers>
9删除: <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
10删除: <provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
9新增: <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer"/>
10新增: <provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6"/>
1111 </providers>
1212 </entityFramework>
1313 <system.data>
1414 <DbProviderFactories>
15删除: <remove invariant="System.Data.SQLite.EF6" />
16删除: <add name="SQLite Data Provider (Entity Framework 6)" invariant="System.Data.SQLite.EF6" description=".NET Framework Data Provider for SQLite (Entity Framework 6)" type="System.Data.SQLite.EF6.SQLiteProviderFactory, System.Data.SQLite.EF6" />
15新增: <remove invariant="System.Data.SQLite.EF6"/>
16新增: <add name="SQLite Data Provider (Entity Framework 6)" invariant="System.Data.SQLite.EF6" description=".NET Framework Data Provider for SQLite (Entity Framework 6)" type="System.Data.SQLite.EF6.SQLiteProviderFactory, System.Data.SQLite.EF6"/>
1717 </DbProviderFactories>
1818 </system.data>
1919 <runtime>
2020 <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
2121 <dependentAssembly>
22删除: <assemblyIdentity name="System.Data.SQLite" publicKeyToken="db937bc2d44ff139" culture="neutral" />
23删除: <bindingRedirect oldVersion="0.0.0.0-1.0.115.5" newVersion="1.0.115.5" />
22新增: <assemblyIdentity name="System.Data.SQLite" publicKeyToken="db937bc2d44ff139" culture="neutral"/>
23新增: <bindingRedirect oldVersion="0.0.0.0-1.0.115.5" newVersion="1.0.115.5"/>
2424 </dependentAssembly>
2525 <dependentAssembly>
26删除: <assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
27删除: <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
26新增: <assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral"/>
27新增: <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0"/>
2828 </dependentAssembly>
2929 <dependentAssembly>
30删除: <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
31删除: <bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" />
30新增: <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral"/>
31新增: <bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1"/>
3232 </dependentAssembly>
3333 </assemblyBinding>
3434 </runtime>
35删除:</configuration>
文件末尾没有换行
35新增:<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>
修改Core/Core.csproj+24 −9看文件
@@ -16,7 +16,7 @@
1616 <AppDesignerFolder>Properties</AppDesignerFolder>
1717 <RootNamespace>Core</RootNamespace>
1818 <AssemblyName>Core</AssemblyName>
19删除: <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
19新增: <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
2020 <FileAlignment>512</FileAlignment>
2121 <Deterministic>true</Deterministic>
2222 <TargetFrameworkProfile />
@@ -137,19 +137,28 @@
137137 <Reference Include="System.Data" />
138138 <Reference Include="System.Net.Http" />
139139 <Reference Include="System.Xml" />
140新增: <Reference Include="websocket-sharp, Version=1.0.2.59611, Culture=neutral, PublicKeyToken=5660b08a1845a91e, processorArchitecture=MSIL">
141新增: <HintPath>..\packages\WebSocketSharp.1.0.3-rc11\lib\websocket-sharp.dll</HintPath>
142新增: </Reference>
140143 <Reference Include="WindowsBase" />
141144 </ItemGroup>
142145 <ItemGroup>
143146 <Compile Include="AppState.cs" />
147新增: <Compile Include="Enums\AppType.cs" />
144148 <Compile Include="Enums\BrowserType.cs" />
145149 <Compile Include="Enums\SleepStatus.cs" />
146150 <Compile Include="Enums\WebPageInfoType.cs" />
151新增: <Compile Include="Event\AppActiveChangedEventArgs.cs" />
152新增: <Compile Include="Event\AppDurationUpdatedEventArgs.cs" />
153新增: <Compile Include="Event\AppObserverEventHandler.cs" />
154新增: <Compile Include="Event\AppTimerEventHandler.cs" />
147155 <Compile Include="Event\EventHandler.cs" />
148156 <Compile Include="Event\BrowserObserverEventHandler.cs" />
157新增: <Compile Include="Event\WebServerEventHandler.cs" />
149158 <Compile Include="Event\ObserverEventHandler.cs" />
150删除: <Compile Include="Librarys\Browser\Favicon\ChromeFaviconManager.cs" />
151删除: <Compile Include="Librarys\Browser\Favicon\IFaviconManager.cs" />
159新增: <Compile Include="Librarys\Browser\Favicon\FaviconDownloader.cs" />
152160 <Compile Include="Librarys\Browser\UrlHelper.cs" />
161新增: <Compile Include="Librarys\Browser\WebSocketEvent.cs" />
153162 <Compile Include="Librarys\FileHelper.cs" />
154163 <Compile Include="Librarys\ProcessHelper.cs" />
155164 <Compile Include="Librarys\RegexHelper.cs" />
@@ -162,7 +171,9 @@
162171 <Compile Include="Librarys\Time.cs" />
163172 <Compile Include="Librarys\Win32API.cs" />
164173 <Compile Include="Models\AppModel.cs" />
174新增: <Compile Include="Models\AppObserver\AppInfo.cs" />
165175 <Compile Include="Models\AppObserver\AppObserverEventArgs.cs" />
176新增: <Compile Include="Models\AppObserver\WindowInfo.cs" />
166177 <Compile Include="Models\CategoryModel.cs" />
167178 <Compile Include="Models\Config\ConfigAttribute.cs" />
168179 <Compile Include="Models\Config\ConfigModel.cs" />
@@ -177,14 +188,14 @@
177188 <Compile Include="Models\Db\WebUrlModel.cs" />
178189 <Compile Include="Models\HoursLogModel.cs" />
179190 <Compile Include="Models\DailyLogModel.cs" />
191新增: <Compile Include="Models\WebPage\NotifyWeb.cs" />
180192 <Compile Include="Models\WebPage\Site.cs" />
181193 <Compile Include="Properties\AssemblyInfo.cs" />
182194 <Compile Include="Servicers\Instances\AppConfig.cs" />
183195 <Compile Include="Servicers\Instances\AppData.cs" />
184删除: <Compile Include="Servicers\Instances\BrowserObserver.cs" />
196新增: <Compile Include="Servicers\Instances\AppManager.cs" />
197新增: <Compile Include="Servicers\Instances\AppTimerServicer.cs" />
185198 <Compile Include="Servicers\Instances\Categorys.cs" />
186删除: <Compile Include="Servicers\Instances\MSEdgeBrowserWatch.cs" />
187删除: <Compile Include="Servicers\Instances\ChromeBrowserWatch.cs" />
188199 <Compile Include="Servicers\Instances\Data.cs" />
189200 <Compile Include="Librarys\Logger.cs" />
190201 <Compile Include="Servicers\Instances\Database.cs" />
@@ -195,9 +206,11 @@
195206 <Compile Include="Servicers\Instances\Sleepdiscover.cs" />
196207 <Compile Include="Servicers\Instances\WebData.cs" />
197208 <Compile Include="Servicers\Instances\WebFilter.cs" />
209新增: <Compile Include="Servicers\Instances\WebServer.cs" />
210新增: <Compile Include="Servicers\Instances\WindowManager.cs" />
198211 <Compile Include="Servicers\Interfaces\IAppConfig.cs" />
199删除: <Compile Include="Servicers\Interfaces\IBrowserWatcher.cs" />
200删除: <Compile Include="Servicers\Interfaces\IBrowserObserver.cs" />
212新增: <Compile Include="Servicers\Interfaces\IAppManager.cs" />
213新增: <Compile Include="Servicers\Interfaces\IAppTimerServicer.cs" />
201214 <Compile Include="Servicers\Interfaces\ICategorys.cs" />
202215 <Compile Include="Servicers\Interfaces\IAppData.cs" />
203216 <Compile Include="Servicers\Interfaces\IData.cs" />
@@ -208,7 +221,8 @@
208221 <Compile Include="Servicers\Interfaces\ISleepdiscover.cs" />
209222 <Compile Include="Servicers\Interfaces\IWebData.cs" />
210223 <Compile Include="Servicers\Interfaces\IWebFilter.cs" />
211删除: <Compile Include="Servicers\Instances\VivaldiBrowserWatch.cs" />
224新增: <Compile Include="Servicers\Interfaces\IWebServer.cs" />
225新增: <Compile Include="Servicers\Interfaces\IWindowManager.cs" />
212226 </ItemGroup>
213227 <ItemGroup>
214228 <None Include="App.config" />
@@ -225,6 +239,7 @@
225239 <EmbedInteropTypes>True</EmbedInteropTypes>
226240 </COMReference>
227241 </ItemGroup>
242新增: <ItemGroup />
228243 <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
229244 <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
230245 <PropertyGroup>
新增Core/Event/WebServerEventHandler.cs+12 −0看文件
@@ -0,0 +1,12 @@
1新增:using Core.Models.AppObserver;
2新增:using Core.Models.WebPage;
3新增:using System;
4新增:using System.Collections.Generic;
5新增:using System.Linq;
6新增:using System.Text;
7新增:using System.Threading.Tasks;
8新增:
9新增:namespace Core.Event
10新增:{
11新增: public delegate void WebServerEventHandler(NotifyWeb args);
12新增:}
删除Core/Librarys/Browser/Favicon/ChromeFaviconManager.cs+0 −137
@@ -1,137 +0,0 @@
1删除:using Core.Enums;
2删除:using System;
3删除:using System.Collections.Generic;
4删除:using System.Data.SQLite;
5删除:using System.Diagnostics;
6删除:using System.Drawing;
7删除:using System.IO;
8删除:using System.Linq;
9删除:using System.Net;
10删除:using System.Security.Cryptography;
11删除:using System.Security.Policy;
12删除:using System.Text;
13删除:using System.Threading;
14删除:using System.Threading.Tasks;
15删除:
16删除:namespace Core.Librarys.Browser.Favicon
17删除:{
18删除: public class ChromeFaviconManager : IFaviconManager
19删除: {
20删除: private readonly string _chromeFaviconsPath;
21删除: private readonly string _faviconsTempPath;
22删除: private readonly string _taiFaviconsPath;
23删除: public ChromeFaviconManager(BrowserType browserType = BrowserType.Chrome)
24删除: {
25删除: var localAppDataDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
26删除:
27删除: switch (browserType)
28删除: {
29删除: case BrowserType.Chrome:
30删除: _chromeFaviconsPath = Path.Combine(localAppDataDir, "Google", "Chrome", "User Data", "Default", "Favicons");
31删除: break;
32删除: case BrowserType.MSEdge:
33删除: _chromeFaviconsPath = Path.Combine(localAppDataDir, "Microsoft", "Edge", "User Data", "Default", "Favicons");
34删除: break;
35删除: case BrowserType.Vivaldi:
36删除: _chromeFaviconsPath = Path.Combine(localAppDataDir, "Vivaldi", "User Data", "Default", "Favicons");
37删除: break;
38删除: }
39删除: _faviconsTempPath = $"{_chromeFaviconsPath}_tai.temp";
40删除: _taiFaviconsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "WebFavicons");
41删除: if (!File.Exists(_chromeFaviconsPath))
42删除: {
43删除: throw new FileNotFoundException("favicons文件路径没有找到");
44删除: }
45删除: if (!Directory.Exists(_taiFaviconsPath))
46删除: {
47删除: Directory.CreateDirectory(_taiFaviconsPath);
48删除: }
49删除: }
50删除: public async Task<object> GetIconDataAsync(string url)
51删除: {
52删除: if (string.IsNullOrEmpty(url)) { throw new ArgumentNullException("url"); }
53删除:
54删除: url = UrlHelper.ChromeURLEncode(url);
55删除:
56删除: var result = await Task.Run(() =>
57删除: {
58删除: byte[] icon = { };
59删除: try
60删除: {
61删除: File.Copy(_chromeFaviconsPath, _faviconsTempPath, true);
62删除:
63删除: using (var con = new SQLiteConnection($"Data Source={_faviconsTempPath}"))
64删除: {
65删除: con.Open();
66删除:
67删除: string iconId = GetIconId(url, con);
68删除:
69删除: if (iconId != string.Empty)
70删除: {
71删除: using (var cmd = new SQLiteCommand($"select * from favicon_bitmaps where icon_id={iconId} order by width desc LIMIT 1", con))
72删除: {
73删除: using (SQLiteDataReader dr = cmd.ExecuteReader())
74删除: {
75删除: if (dr.Read())
76删除: {
77删除: icon = (System.Byte[])dr["image_data"];
78删除: }
79删除: }
80删除: }
81删除: }
82删除: }
83删除:
84删除: File.Delete(_faviconsTempPath);
85删除: }
86删除: catch (Exception ex)
87删除: {
88删除: Logger.Error(ex.ToString());
89删除: }
90删除: return icon;
91删除: });
92删除:
93删除: return result.Length == 0 ? null : result;
94删除: }
95删除:
96删除: private string GetIconId(string url_, SQLiteConnection con_)
97删除: {
98删除: string iconId = string.Empty;
99删除: string sqlStr = url_.IndexOf("://") == -1 ? $"%{url_}%" : $"{url_}%";
100删除: using (var cmd = new SQLiteCommand($"select * from icon_mapping where page_url like'{sqlStr}' LIMIT 1", con_))
101删除: {
102删除: using (SQLiteDataReader dr = cmd.ExecuteReader())
103删除: {
104删除: if (dr.Read())
105删除: {
106删除: iconId = dr["icon_id"].ToString();
107删除: }
108删除: }
109删除: }
110删除: return iconId;
111删除: }
112删除:
113删除: public async Task<string> SaveToLocalIconAsync(object data)
114删除: {
115删除: if (data == null) { throw new ArgumentNullException("data"); }
116删除: return await Task.Run(() =>
117删除: {
118删除: var icon = data as byte[];
119删除: string iconPath = string.Empty;
120删除: using (var md5 = MD5.Create())
121删除: {
122删除: var hash = md5.ComputeHash(icon);
123删除: var md5Str = BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
124删除:
125删除: iconPath = Path.Combine(_taiFaviconsPath, $"{md5Str}.png");
126删除: if (!File.Exists(iconPath))
127删除: {
128删除: File.WriteAllBytes(iconPath, icon);
129删除: }
130删除: iconPath = Path.Combine("WebFavicons", $"{md5Str}.png");
131删除: }
132删除: return iconPath;
133删除: });
134删除:
135删除: }
136删除: }
137删除:}
新增Core/Librarys/Browser/Favicon/FaviconDownloader.cs+50 −0看文件
@@ -0,0 +1,50 @@
1新增:using System;
2新增:using System.Collections.Generic;
3新增:using System.IO;
4新增:using System.Linq;
5新增:using System.Net;
6新增:using System.Text;
7新增:using System.Threading.Tasks;
8新增:
9新增:namespace Core.Librarys.Browser.Favicon
10新增:{
11新增: public class FaviconDownloader
12新增: {
13新增: /// <summary>
14新增: /// 下载文件
15新增: /// </summary>
16新增: /// <param name="url_">文件远程地址</param>
17新增: /// <param name="savePath_">本地保存路径</param>
18新增: public static async Task<string> DownloadAsync(string url_, string saveName_)
19新增: {
20新增: if (string.IsNullOrEmpty(url_)) return string.Empty;
21新增:
22新增: string savePath = Path.Combine(FileHelper.GetRootDirectory(), "WebFavicons", saveName_);
23新增: string dir = Path.GetDirectoryName(savePath);
24新增: // 暂时不支持svg格式ico,尝试获取png
25新增: url_ = url_.Replace(".svg", ".png");
26新增:
27新增: if (!Directory.Exists(dir))
28新增: {
29新增: Directory.CreateDirectory(dir);
30新增: }
31新增: if (File.Exists(savePath))
32新增: {
33新增: return savePath;
34新增: }
35新增: try
36新增: {
37新增: using (var web = new WebClient())
38新增: {
39新增: await web.DownloadFileTaskAsync(url_, savePath);
40新增: return savePath;
41新增: }
42新增: }
43新增: catch (Exception e)
44新增: {
45新增: Logger.Error("下载图标失败," + e);
46新增: return string.Empty;
47新增: }
48新增: }
49新增: }
50新增:}
删除Core/Librarys/Browser/Favicon/IFaviconManager.cs+0 −24
@@ -1,24 +0,0 @@
1删除:using System;
2删除:using System.Collections.Generic;
3删除:using System.Linq;
4删除:using System.Text;
5删除:using System.Threading.Tasks;
6删除:
7删除:namespace Core.Librarys.Browser.Favicon
8删除:{
9删除: public interface IFaviconManager
10删除: {
11删除: /// <summary>
12删除: /// 保存图标数据到Tai目录下并返回图标相对路径
13删除: /// </summary>
14删除: /// <param name="data"></param>
15删除: /// <returns></returns>
16删除: Task<string> SaveToLocalIconAsync(object data);
17删除: /// <summary>
18删除: /// 通过URL链接获取Favicon图标数据
19删除: /// </summary>
20删除: /// <param name="url"></param>
21删除: /// <returns></returns>
22删除: Task<object> GetIconDataAsync(string url);
23删除: }
24删除:}
修改Core/Librarys/Browser/UrlHelper.cs+1 −1看文件
@@ -98,7 +98,7 @@ namespace Core.Librarys.Browser
9898 {
9999 url_ = url_.Replace("http://", string.Empty);
100100 url_ = url_.Replace("https://", string.Empty);
101删除: return url_.IndexOf("/") == -1;
101新增: return url_.IndexOf("/") == -1 || url_.Last() == '/';
102102 }
103103
104104 /// <summary>
新增Core/Librarys/Browser/WebSocketEvent.cs+22 −0看文件
@@ -0,0 +1,22 @@
1新增:using Core.Event;
2新增:using Core.Models.WebPage;
3新增:using System;
4新增:using System.Collections.Generic;
5新增:using System.Linq;
6新增:using System.Text;
7新增:using System.Threading.Tasks;
8新增:using WebSocketSharp;
9新增:using WebSocketSharp.Server;
10新增:
11新增:namespace Core.Librarys.Browser
12新增:{
13新增: public class WebSocketEvent : WebSocketBehavior
14新增: {
15新增: public static event WebServerEventHandler OnWebLog;
16新增:
17新增: public static void Invoke(NotifyWeb args_)
18新增: {
19新增: OnWebLog?.Invoke(args_);
20新增: }
21新增: }
22新增:}
修改Core/Models/Config/GeneralModel.cs+1 −1看文件
@@ -60,7 +60,7 @@ namespace Core.Models.Config
6060 /// <summary>
6161 /// 是否启用网站记录功能
6262 /// </summary>
63删除: [Config(Name = "网站浏览统计", Description = "统计浏览器的网站访问数据,支持:Google Chrome、MSEdge、Vivaldi", Group = "功能", IsBeta = true)]
63新增: [Config(Name = "网站浏览统计", Description = "统计浏览器的网站访问数据,支持:Google Chrome、MSEdge或任何能够安装Chrome拓展的浏览器。在浏览器拓展管理中启用开发模式,选择加载已解压插件,选择Tai浏览器插件。", Group = "功能", IsBeta = true)]
6464 public bool IsWebEnabled { get; set; } = false;
6565 }
6666}
文件末尾没有换行
新增Core/Models/WebPage/NotifyWeb.cs+25 −0看文件
@@ -0,0 +1,25 @@
1新增:using System;
2新增:using System.Collections.Generic;
3新增:using System.Linq;
4新增:using System.Text;
5新增:using System.Threading.Tasks;
6新增:
7新增:namespace Core.Models.WebPage
8新增:{
9新增: public class NotifyWeb
10新增: {
11新增: public string Url { get; set; }
12新增: public string Title { get; set; }
13新增: public string Icon { get; set; }
14新增: public int ActiveTime { get; set; }
15新增: public int Duration { get; set; }
16新增: public DateTime ActiveDateTime
17新增: {
18新增: get
19新增: {
20新增: DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
21新增: return dateTime.AddSeconds(ActiveTime).ToLocalTime();
22新增: }
23新增: }
24新增: }
25新增:}
删除Core/Servicers/Instances/BrowserObserver.cs+0 −323
@@ -1,323 +0,0 @@
1删除:using Core.Enums;
2删除:using Core.Event;
3删除:using Core.Librarys;
4删除:using Core.Librarys.Browser;
5删除:using Core.Librarys.Browser.Favicon;
6删除:using Core.Librarys.SQLite;
7删除:using Core.Models.WebPage;
8删除:using Core.Servicers.Interfaces;
9删除:using NPOI.SS.Formula.Functions;
10删除:using System;
11删除:using System.Collections.Generic;
12删除:using System.Data.SQLite;
13删除:using System.Diagnostics;
14删除:using System.IO;
15删除:using System.Linq;
16删除:using System.Security.Policy;
17删除:using System.Text;
18删除:using System.Threading;
19删除:using System.Threading.Tasks;
20删除:using System.Windows.Automation;
21删除:using System.Windows.Forms;
22删除:using System.Windows.Threading;
23删除:using Site = Core.Models.WebPage.Site;
24删除:
25删除:namespace Core.Servicers.Instances
26删除:{
27删除: public class BrowserObserver : IBrowserObserver
28删除: {
29删除: public event BrowserObserverEventHandler OnSiteChanged;
30删除:
31删除: private readonly IAppObserver _appObserver;
32删除: private readonly IWebData _webData;
33删除: private readonly IWebFilter _webFilter;
34删除: private readonly ISleepdiscover _sleepdiscover;
35删除: private readonly IDateTimeObserver _dateTimeObserver;
36删除:
37删除: private IBrowserWatcher _browserWatcher;
38删除: private bool _isStart = false;
39删除: /// <summary>
40删除: /// 忽略的URL集合
41删除: /// </summary>
42删除: private readonly string[] _ignoreURL = { "about:blank" };
43删除: /// <summary>
44删除: /// 当前浏览站点
45删除: /// </summary>
46删除: private Site _activeSite = null;
47删除: /// <summary>
48删除: /// 浏览开始时间
49删除: /// </summary>
50删除: private DateTime _activeStartTime = DateTime.MinValue;
51删除: // 已保存图标的链接
52删除: private List<string> _savedIconUrls = new List<string>();
53删除: public BrowserObserver(IAppObserver appObserver_, IWebData webData_, IWebFilter webFilter_, ISleepdiscover sleepdiscover_, IDateTimeObserver dateTimeObserver_)
54删除: {
55删除: _appObserver = appObserver_;
56删除: _webData = webData_;
57删除: _webFilter = webFilter_;
58删除: _sleepdiscover = sleepdiscover_;
59删除: _dateTimeObserver = dateTimeObserver_;
60删除: }
61删除: public void Start()
62删除: {
63删除: if (_isStart)
64删除: {
65删除: return;
66删除: }
67删除: _isStart = true;
68删除: _appObserver.OnAppActive += AppObserver_OnAppActive;
69删除: _sleepdiscover.SleepStatusChanged += _sleepdiscover_SleepStatusChanged;
70删除: _dateTimeObserver.OnDateTimeChanging += _dateTimeObserver_OnDateTimeChanging;
71删除: }
72删除:
73删除: private void _dateTimeObserver_OnDateTimeChanging(object sender, DateTime e)
74删除: {
75删除: SaveTime(false);
76删除: }
77删除:
78删除: public void Stop()
79删除: {
80删除: _appObserver.OnAppActive -= AppObserver_OnAppActive;
81删除: _sleepdiscover.SleepStatusChanged -= _sleepdiscover_SleepStatusChanged;
82删除: _dateTimeObserver.OnDateTimeChanging -= _dateTimeObserver_OnDateTimeChanging;
83删除:
84删除: _isStart = false;
85删除: StopWatch();
86删除: }
87删除:
88删除: private void _sleepdiscover_SleepStatusChanged(SleepStatus sleepStatus)
89删除: {
90删除: if (sleepStatus == SleepStatus.Sleep)
91删除: {
92删除: // 睡眠状态
93删除: Stop();
94删除: }
95删除: else
96删除: {
97删除: // 唤醒
98删除: Start();
99删除: }
100删除: }
101删除:
102删除: private void AppObserver_OnAppActive(Models.AppObserver.AppObserverEventArgs args)
103删除: {
104删除: switch (args.ProcessName)
105删除: {
106删除: case "chrome":
107删除: StartWatch(BrowserType.Chrome, args.Handle);
108删除: break;
109删除: case "msedge":
110删除: StartWatch(BrowserType.MSEdge, args.Handle);
111删除: break;
112删除: case "vivaldi":
113删除: StartWatch(BrowserType.Vivaldi, args.Handle);
114删除: break;
115删除: default:
116删除: StopWatch();
117删除: break;
118删除:
119删除: }
120删除: }
121删除:
122删除: private void StartWatch(BrowserType browserType, IntPtr handle)
123删除: {
124删除: StopWatch();
125删除:
126删除: switch (browserType)
127删除: {
128删除: case BrowserType.Chrome:
129删除: _browserWatcher = new ChromeBrowserWatch();
130删除: break;
131删除: case BrowserType.Vivaldi:
132删除: _browserWatcher = new VivaldiBrowserWatch();
133删除: break;
134删除: case BrowserType.MSEdge:
135删除: _browserWatcher = new MSEdgeBrowserWatch();
136删除: break;
137删除: }
138删除:
139删除: if (_browserWatcher == null)
140删除: {
141删除: Logger.Error("无法启动浏览器监听,浏览器类型:" + browserType.ToString());
142删除: return;
143删除: }
144删除:
145删除: _browserWatcher.OnSiteChanged += BrowserWatcher_OnSiteChanged; ;
146删除: _browserWatcher.StartWatch(handle);
147删除: }
148删除:
149删除: private void BrowserWatcher_OnSiteChanged(BrowserType browserType, Models.WebPage.Site site)
150删除: {
151删除: Debug.WriteLine(site.ToString());
152删除:
153删除: // 过滤URL
154删除: if (_webFilter.IsIgnore(site.Url))
155删除: {
156删除: Debug.WriteLine($"已被过滤的URL {site.Url}");
157删除: return;
158删除: }
159删除: //Debug.WriteLine($"域名:{UrlHelper.GetDomain(site.Url)}");
160删除: // 更新网页时间
161删除: SaveTime();
162删除:
163删除: _activeSite = site;
164删除: _activeStartTime = DateTime.Now;
165删除:
166删除: OnSiteChanged?.Invoke(browserType, site);
167删除:
168删除: // 更新网页图标
169删除: UpdateFavicon(browserType, site);
170删除: }
171删除:
172删除:
173删除: #region saveTime
174删除: private void SaveTime(bool isReset_ = true)
175删除: {
176删除: if (_activeSite != null && _activeStartTime != DateTime.MinValue)
177删除: {
178删除: SaveTime(new Site(_activeSite), new DateTime(_activeStartTime.Ticks));
179删除:
180删除: if (isReset_)
181删除: {
182删除: _activeStartTime = DateTime.MinValue;
183删除: _activeSite = null;
184删除: }
185删除: else
186删除: {
187删除: _activeStartTime = DateTime.Now;
188删除: }
189删除: }
190删除: }
191删除: private void SaveTime(Site site_, DateTime startTime_)
192删除: {
193删除: Task.Run(() =>
194删除: {
195删除: if (!IsTrueURL(site_.Url))
196删除: {
197删除: return;
198删除: }
199删除:
200删除: TimeSpan browseTime = DateTime.Now - startTime_;
201删除: int seconds = (int)(browseTime.TotalSeconds == 0 ? 1 : browseTime.TotalSeconds);
202删除:
203删除: if (seconds > 0)
204删除: {
205删除: // 更新到数据库
206删除: _webData.AddUrlBrowseTime(site_, seconds, startTime_);
207删除: Debug.WriteLine($"网页:{site_.Title} 浏览了:{seconds}秒。开始时间:{startTime_}");
208删除: }
209删除: });
210删除: }
211删除:
212删除: #endregion
213删除:
214删除: #region updatefavicon
215删除: /// <summary>
216删除: /// 更新获取网页favicon到tai数据库中
217删除: /// </summary>
218删除: /// <param name="browserType"></param>
219删除: /// <param name="site"></param>
220删除: private void UpdateFavicon(BrowserType browserType, Models.WebPage.Site site)
221删除: {
222删除: if (!IsTrueURL(site.Url))
223删除: {
224删除: return;
225删除: }
226删除:
227删除: if (_savedIconUrls.Contains(site.Url))
228删除: {
229删除: // 已经缓存的链接不再重复获取
230删除: return;
231删除: }
232删除:
233删除: if (_savedIconUrls.Count > 100)
234删除: {
235删除: // 限制缓存链接条数
236删除: _savedIconUrls.RemoveAt(0);
237删除: }
238删除:
239删除: Task.Run(async () =>
240删除: {
241删除: try
242删除: {
243删除: // 获取favicon
244删除: IFaviconManager fm = null;
245删除: switch (browserType)
246删除: {
247删除: // chrome内核的用同一个图标管理器
248删除: case BrowserType.Chrome:
249删除: case BrowserType.MSEdge:
250删除: case BrowserType.Vivaldi:
251删除: fm = new ChromeFaviconManager(browserType);
252删除: break;
253删除: }
254删除: if (fm == null)
255删除: {
256删除: throw new Exception("FaviconManager is null!");
257删除: }
258删除:
259删除: var data = await fm.GetIconDataAsync(site.Url);
260删除: if (data == null)
261删除: {
262删除: // 浏览器可能还没更新缓存,延迟再获取一次
263删除: Thread.Sleep(3000);
264删除: data = await fm.GetIconDataAsync(site.Url);
265删除: }
266删除: if (data != null)
267删除: {
268删除: // 保存到 tai目录下
269删除: string path = await fm.SaveToLocalIconAsync(data);
270删除:
271删除: // 更新到数据库
272删除: _webData.UpdateUrlFavicon(site, path);
273删除:
274删除: _savedIconUrls.Add(site.Url);
275删除: }
276删除: else
277删除: {
278删除: // 如果无法获取则使用站点图标
279删除: string domain = UrlHelper.GetDomain(site.Url);
280删除: // 读取站点数据
281删除: var webSite = _webData.GetWebSite(domain);
282删除:
283删除: if (webSite != null)
284删除: {
285删除: _webData.UpdateUrlFavicon(site, webSite.IconFile);
286删除: }
287删除: }
288删除: }
289删除: catch (Exception ex)
290删除: {
291删除: Logger.Error(ex.ToString());
292删除: }
293删除: });
294删除:
295删除:
296删除: }
297删除: #endregion
298删除:
299删除: /// <summary>
300删除: /// 指示URL是否正确
301删除: /// </summary>
302删除: /// <param name="url"></param>
303删除: /// <returns></returns>
304删除: private bool IsTrueURL(string url)
305删除: {
306删除: return !string.IsNullOrEmpty(url) && !_ignoreURL.Contains(url);
307删除: }
308删除: private void StopWatch()
309删除: {
310删除: if (_browserWatcher != null)
311删除: {
312删除: _browserWatcher.OnSiteChanged -= BrowserWatcher_OnSiteChanged;
313删除: _browserWatcher.StopWatch();
314删除: _browserWatcher = null;
315删除: }
316删除:
317删除: // 保存时间
318删除: SaveTime();
319删除: }
320删除:
321删除:
322删除: }
323删除:}
删除Core/Servicers/Instances/ChromeBrowserWatch.cs+0 −220
@@ -1,220 +0,0 @@
1删除:using Core.Enums;
2删除:using Core.Event;
3删除:using Core.Librarys;
4删除:using Core.Librarys.Browser.Favicon;
5删除:using Core.Models.WebPage;
6删除:using Core.Servicers.Interfaces;
7删除:using NPOI.SS.Formula.Functions;
8删除:using System;
9删除:using System.Collections.Generic;
10删除:using System.Data.SQLite;
11删除:using System.Diagnostics;
12删除:using System.IO;
13删除:using System.Linq;
14删除:using System.Security.Cryptography;
15删除:using System.Text;
16删除:using System.Threading.Tasks;
17删除:using System.Windows.Automation;
18删除:using System.Windows.Interop;
19删除:using UIAutomationClient;
20删除:
21删除:namespace Core.Servicers.Instances
22删除:{
23删除: public class ChromeBrowserWatch : IBrowserWatcher
24删除: {
25删除: public event BrowserObserverEventHandler OnSiteChanged;
26删除: private string url, title;
27删除: CUIAutomation automation;
28删除: // 根元素(监听站点切换使用)
29删除: IUIAutomationElement rootElement;
30删除: // 主元素(寻找URL使用)
31删除: IUIAutomationElement mainElement;
32删除: // 站点切换事件
33删除: AutomationPropertyChangedEventHandler siteChangedEventHandler;
34删除:
35删除: public ChromeBrowserWatch()
36删除: {
37删除: automation = new CUIAutomation();
38删除: siteChangedEventHandler = new AutomationPropertyChangedEventHandler(OnNameChanged);
39删除: }
40删除:
41删除: public void StartWatch(IntPtr handle)
42删除: {
43删除: try
44删除: {
45删除: if (handle == IntPtr.Zero)
46删除: {
47删除: throw new Exception("未传入浏览器句柄");
48删除: }
49删除:
50删除: Win32API.GetWindowThreadProcessId(handle, out int processID);
51删除: Process process = Process.GetProcessById(processID);
52删除: if (process == null)
53删除: {
54删除: return;
55删除: }
56删除:
57删除: Debug.WriteLine("启动浏览器监听,目标:" + process.ProcessName);
58删除: // 搜索根元素
59删除: rootElement = automation.ElementFromHandle(handle);
60删除: if (rootElement == null)
61删除: {
62删除: throw new Exception("找不到根元素!");
63删除: }
64删除: // 找到窗口
65删除: var condtionPanel = automation.CreatePropertyCondition(30003, 50033);
66删除: var condtionName = automation.CreatePropertyCondition(30005, "Google Chrome");
67删除: var condtionFindWindow = automation.CreateAndCondition(condtionPanel, condtionName);
68删除: var window = rootElement.FindFirst(TreeScope.TreeScope_Children, condtionFindWindow);
69删除: if (window != null)
70删除: {
71删除: // 第二个窗口
72删除: mainElement = window.FindFirst(TreeScope.TreeScope_Children, automation.CreateTrueCondition());
73删除: }
74删除: else
75删除: {
76删除: mainElement = rootElement;
77删除: Debug.WriteLine("没有找到主窗口,使用根元素作为主元素");
78删除: }
79删除:
80删除:
81删除: if (mainElement == null)
82删除: {
83删除: throw new Exception("找不到主元素!");
84删除: }
85删除:
86删除: // 注册事件
87删除: IUIAutomationCacheRequest cacheRequest = automation.CreateCacheRequest();
88删除: cacheRequest.AddProperty(30005);
89删除: int[] props = { 30005 };
90删除:
91删除: automation.AddPropertyChangedEventHandler(rootElement, TreeScope.TreeScope_Element, cacheRequest, siteChangedEventHandler, props);
92删除: Debug.WriteLine("启动浏览器监听成功");
93删除:
94删除: Handle(process.MainWindowTitle);
95删除: }
96删除: catch (Exception e)
97删除: {
98删除: Logger.Error(e.ToString());
99删除: }
100删除: }
101删除:
102删除: private void OnNameChanged(IUIAutomationElement s, int p, object v)
103删除: {
104删除: Handle(v.ToString());
105删除: }
106删除:
107删除: #region AutomationPropertyChangedEventHandler
108删除: private class AutomationPropertyChangedEventHandler : IUIAutomationPropertyChangedEventHandler
109删除: {
110删除: public AutomationPropertyChangedEventHandler(Action<IUIAutomationElement, int, object> action)
111删除: {
112删除: if (action == null)
113删除: throw new ArgumentNullException(nameof(action));
114删除:
115删除: Action = action;
116删除: }
117删除:
118删除: public Action<IUIAutomationElement, int, object> Action { get; }
119删除: public void HandlePropertyChangedEvent(IUIAutomationElement sender, int propertyId, object newValue) => Action(sender, propertyId, newValue);
120删除: }
121删除: #endregion
122删除:
123删除: public void StopWatch()
124删除: {
125删除: try
126删除: {
127删除: Debug.WriteLine("已停止浏览器监听");
128删除: automation.RemovePropertyChangedEventHandler(rootElement, siteChangedEventHandler);
129删除: }
130删除: catch (Exception e)
131删除: {
132删除: Logger.Error(e.ToString());
133删除: }
134删除: }
135删除:
136删除: private string FormatTitle(string title)
137删除: {
138删除: if (string.IsNullOrEmpty(title))
139删除: {
140删除: return title;
141删除: }
142删除: int length = title.LastIndexOf('-') - 1;
143删除: if (length < 1)
144删除: {
145删除: length = 1;
146删除: }
147删除:
148删除: return title.Substring(0, length);
149删除: }
150删除:
151删除: private async void Handle(string title)
152删除: {
153删除: title = FormatTitle(title);
154删除: //Debug.WriteLine($"切换标题 {title}");
155删除: Site site = null;
156删除: if (!string.IsNullOrEmpty(title))
157删除: {
158删除: site = SiteCache.Get(title);
159删除: }
160删除:
161删除: if (site == null)
162删除: {
163删除: string url = await GetURLSync();
164删除: site = new Site()
165删除: {
166删除: Url = url,
167删除: Title = title
168删除: };
169删除: SiteCache.Set(title, url);
170删除: }
171删除:
172删除: ResponseEvent(site.Url, site.Title);
173删除: }
174删除:
175删除: #region 获取浏览器当前URL
176删除: /// <summary>
177删除: /// 获取浏览器当前URL
178删除: /// </summary>
179删除: /// <returns></returns>
180删除: private async Task<string> GetURLSync()
181删除: {
182删除: return await Task.Run(() =>
183删除: {
184删除: string result = string.Empty;
185删除: try
186删除: {
187删除: var condtionEdit = automation.CreatePropertyCondition(30003, 50004);
188删除: var condtionAccessKey = automation.CreatePropertyCondition(30007, "Ctrl+L");
189删除: var condtion = automation.CreateAndCondition(condtionEdit, condtionAccessKey);
190删除: var addressElement = rootElement.FindFirst(TreeScope.TreeScope_Descendants, condtion);
191删除: if (addressElement != null)
192删除: {
193删除: result = ((IUIAutomationValuePattern)addressElement.GetCurrentPattern(10002)).CurrentValue;
194删除: }
195删除: }
196删除: catch (Exception e)
197删除: {
198删除: Logger.Error(e.ToString());
199删除: }
200删除: return result;
201删除: });
202删除:
203删除: }
204删除: #endregion
205删除:
206删除: private void ResponseEvent(string url, string title)
207删除: {
208删除: if (url != this.url)
209删除: {
210删除: this.url = url;
211删除: this.title = title;
212删除: OnSiteChanged?.Invoke(BrowserType.Chrome, new Models.WebPage.Site()
213删除: {
214删除: Url = url,
215删除: Title = title
216删除: });
217删除: }
218删除: }
219删除: }
220删除:}
删除Core/Servicers/Instances/MSEdgeBrowserWatch.cs+0 −243
@@ -1,243 +0,0 @@
1删除:using Core.Enums;
2删除:using Core.Event;
3删除:using Core.Librarys;
4删除:using Core.Librarys.Browser.Favicon;
5删除:using Core.Models.WebPage;
6删除:using Core.Servicers.Interfaces;
7删除:using NPOI.SS.Formula.Functions;
8删除:using System;
9删除:using System.Collections.Generic;
10删除:using System.Data.SQLite;
11删除:using System.Diagnostics;
12删除:using System.IO;
13删除:using System.Linq;
14删除:using System.Security.Cryptography;
15删除:using System.Text;
16删除:using System.Threading.Tasks;
17删除:using System.Windows.Automation;
18删除:using System.Windows.Interop;
19删除:using UIAutomationClient;
20删除:
21删除:namespace Core.Servicers.Instances
22删除:{
23删除: public class MSEdgeBrowserWatch : IBrowserWatcher
24删除: {
25删除: public event BrowserObserverEventHandler OnSiteChanged;
26删除: private string url, title;
27删除: CUIAutomation automation;
28删除: // 根元素(监听站点切换使用)
29删除: IUIAutomationElement rootElement;
30删除: // 主元素(寻找URL使用)
31删除: IUIAutomationElement mainElement;
32删除:
33删除: IntPtr hook;
34删除: Win32API.WinEventDelegate winEventDelegate;
35删除: public MSEdgeBrowserWatch()
36删除: {
37删除: automation = new CUIAutomation();
38删除: winEventDelegate = new Win32API.WinEventDelegate(WinEventProc);
39删除: }
40删除:
41删除: private void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
42删除: {
43删除: //Debug.WriteLine("idObject:" + idObject + ",idChild:" + idChild);
44删除:
45删除: if (idObject == 0 && idChild == 0)
46删除: {
47删除: Debug.WriteLine("切换选项卡 -> " + dwmsEventTime);
48删除: Handle();
49删除: }
50删除: }
51删除:
52删除: public void StartWatch(IntPtr handle)
53删除: {
54删除: try
55删除: {
56删除: if (handle == IntPtr.Zero)
57删除: {
58删除: throw new Exception("未传入浏览器句柄");
59删除: }
60删除:
61删除: Win32API.GetWindowThreadProcessId(handle, out int processID);
62删除: Process process = Process.GetProcessById(processID);
63删除: if (process == null)
64删除: {
65删除: return;
66删除: }
67删除:
68删除: Debug.WriteLine("启动浏览器监听,目标:" + process.ProcessName + "," + handle);
69删除: // 搜索根元素
70删除: rootElement = automation.ElementFromHandle(handle);
71删除: if (rootElement == null)
72删除: {
73删除: throw new Exception("找不到根元素!");
74删除: }
75删除: // 找到窗口
76删除: var condtionPanel = automation.CreatePropertyCondition(30003, 50033);
77删除: var condtionName = automation.CreatePropertyCondition(30012, "BrowserRootView");
78删除: var condtionFindWindow = automation.CreateAndCondition(condtionPanel, condtionName);
79删除: var window = rootElement.FindFirst(TreeScope.TreeScope_Children, condtionFindWindow);
80删除: if (window != null)
81删除: {
82删除: // 第二个窗口
83删除: mainElement = window.FindFirst(TreeScope.TreeScope_Children, automation.CreateTrueCondition());
84删除: }
85删除: else
86删除: {
87删除: mainElement = rootElement;
88删除: Debug.WriteLine("没有找到主窗口,使用根元素作为主元素");
89删除: }
90删除:
91删除:
92删除: if (mainElement == null)
93删除: {
94删除: throw new Exception("找不到主元素!");
95删除: }
96删除:
97删除: // 注册事件
98删除:
99删除: //// 找到窗口
100删除: //var condtionTab = automation.CreatePropertyCondition(30003, 50018);
101删除: //var condtionClassName = automation.CreatePropertyCondition(30012, "TabStripRegionView");
102删除: //var tabElement = mainElement.FindFirst(TreeScope.TreeScope_Descendants, automation.CreateAndCondition(condtionTab, condtionClassName));
103删除: hook = Win32API.SetWinEventHook(0x800C, 0x800C, handle, winEventDelegate, 0, 0, 0);
104删除:
105删除: Debug.WriteLine("启动浏览器监听成功");
106删除:
107删除: Handle();
108删除: }
109删除: catch (Exception e)
110删除: {
111删除: Logger.Error(e.ToString());
112删除: }
113删除: }
114删除:
115删除: public void StopWatch()
116删除: {
117删除: try
118删除: {
119删除: Win32API.UnhookWinEvent(hook);
120删除: Debug.WriteLine("已停止浏览器监听");
121删除: }
122删除: catch (Exception e)
123删除: {
124删除: Logger.Error(e.ToString());
125删除: }
126删除: }
127删除:
128删除: private string FormatTitle(string title)
129删除: {
130删除: if (string.IsNullOrEmpty(title))
131删除: {
132删除: return title;
133删除: }
134删除: int length = title.LastIndexOf('-') - 1;
135删除: if (length < 1)
136删除: {
137删除: length = 1;
138删除: }
139删除:
140删除: return title.Substring(0, length);
141删除: }
142删除:
143删除: private async void Handle()
144删除: {
145删除: string title = await GetURLTitleSync();
146删除: title = FormatTitle(title);
147删除: Site site = null;
148删除: if (!string.IsNullOrEmpty(title))
149删除: {
150删除: site = SiteCache.Get(title);
151删除: }
152删除:
153删除: if (site == null)
154删除: {
155删除: string url = await GetURLSync();
156删除: site = new Site()
157删除: {
158删除: Url = url,
159删除: Title = title
160删除: };
161删除: SiteCache.Set(title, url);
162删除: }
163删除:
164删除: ResponseEvent(site.Url, site.Title);
165删除: }
166删除:
167删除: #region 获取浏览器当前URL
168删除: /// <summary>
169删除: /// 获取浏览器当前URL
170删除: /// </summary>
171删除: /// <returns></returns>
172删除: private async Task<string> GetURLSync()
173删除: {
174删除: return await Task.Run(() =>
175删除: {
176删除: string result = string.Empty;
177删除: try
178删除: {
179删除: var condtionEdit = automation.CreatePropertyCondition(30003, 50004);
180删除: var condtionAccessKey = automation.CreatePropertyCondition(30006, "Ctrl+L");
181删除: var condtion = automation.CreateAndCondition(condtionEdit, condtionAccessKey);
182删除: var addressElement = rootElement.FindFirst(TreeScope.TreeScope_Descendants, condtion);
183删除: if (addressElement != null)
184删除: {
185删除: result = ((IUIAutomationValuePattern)addressElement.GetCurrentPattern(10002)).CurrentValue;
186删除: }
187删除: }
188删除: catch (Exception e)
189删除: {
190删除: Logger.Error(e.ToString());
191删除: }
192删除: return result;
193删除: });
194删除:
195删除: }
196删除: #endregion
197删除:
198删除: #region 获取浏览器当前网页标题
199删除: /// <summary>
200删除: /// 获取浏览器当前网页标题
201删除: /// </summary>
202删除: /// <returns></returns>
203删除: private async Task<string> GetURLTitleSync()
204删除: {
205删除: return await Task.Run(() =>
206删除: {
207删除: string result = string.Empty;
208删除: try
209删除: {
210删除: var condtionEdit = automation.CreatePropertyCondition(30003, 50033);
211删除: var condtionCN = automation.CreatePropertyCondition(30012, "BrowserRootView");
212删除: var condtion = automation.CreateAndCondition(condtionEdit, condtionCN);
213删除: var element = rootElement.FindFirst(TreeScope.TreeScope_Descendants, condtion);
214删除: if (element != null)
215删除: {
216删除: result = element.GetCurrentPropertyValue(30005);
217删除: }
218删除: }
219删除: catch (Exception e)
220删除: {
221删除: Logger.Error(e.ToString());
222删除: }
223删除: return result;
224删除: });
225删除:
226删除: }
227删除: #endregion
228删除:
229删除: private void ResponseEvent(string url, string title)
230删除: {
231删除: if (url != this.url)
232删除: {
233删除: this.url = url;
234删除: this.title = title;
235删除: OnSiteChanged?.Invoke(BrowserType.MSEdge, new Models.WebPage.Site()
236删除: {
237删除: Url = url,
238删除: Title = title
239删除: });
240删除: }
241删除: }
242删除: }
243删除:}
修改Core/Servicers/Instances/Main.cs+57 −3看文件
@@ -1,6 +1,8 @@
11using Core.Enums;
22using Core.Event;
33using Core.Librarys;
4新增:using Core.Librarys.Browser;
5新增:using Core.Librarys.Browser.Favicon;
46using Core.Librarys.SQLite;
57using Core.Models;
68using Core.Models.Config;
@@ -10,10 +12,13 @@ using System;
1012using System.Collections.Generic;
1113using System.Data.Entity;
1214using System.Diagnostics;
15新增:using System.Drawing;
1316using System.IO;
1417using System.Linq;
18新增:using System.Security.Cryptography;
1519using System.Text;
1620using System.Text.RegularExpressions;
21新增:using System.Threading;
1722using System.Threading.Tasks;
1823using System.Timers;
1924using System.Windows.Threading;
@@ -31,6 +36,7 @@ namespace Core.Servicers.Instances
3136 private readonly IWebFilter _webFilter;
3237 private readonly IAppTimerServicer _appTimer;
3338 private readonly IWebServer _webServer;
39新增: private readonly IWebData _webData;
3440 // 忽略的进程
3541 private readonly string[] DefaultIgnoreProcess = new string[] {
3642 "Tai",
@@ -84,8 +90,9 @@ namespace Core.Servicers.Instances
8490 IDateTimeObserver dateTimeObserver,
8591 IAppData appData, ICategorys categories,
8692 IWebFilter webFilter_,
87删除: IAppTimerServicer appTimer_,
88删除: IWebServer webServer_)
93新增: IAppTimerServicer appTimer_,
94新增: IWebServer webServer_,
95新增: IWebData webData_)
8996 {
9097 this.appObserver = appObserver;
9198 this.data = data;
@@ -96,6 +103,7 @@ namespace Core.Servicers.Instances
96103 _webFilter = webFilter_;
97104 _appTimer = appTimer_;
98105 _webServer = webServer_;
106新增: _webData = webData_;
99107
100108 IgnoreProcessCacheList = new List<string>();
101109 ConfigIgnoreProcessRegxList = new List<string>();
@@ -104,6 +112,7 @@ namespace Core.Servicers.Instances
104112 sleepdiscover.SleepStatusChanged += Sleepdiscover_SleepStatusChanged;
105113 appConfig.ConfigChanged += AppConfig_ConfigChanged;
106114 _appTimer.OnAppDurationUpdated += _appTimer_OnAppDurationUpdated;
115新增: WebSocketEvent.OnWebLog += WebSocketEvent_OnWebLog;
107116 }
108117
109118 private void AppConfig_ConfigChanged(ConfigModel oldConfig, ConfigModel newConfig)
@@ -167,7 +176,10 @@ namespace Core.Servicers.Instances
167176 // appTimer必须比Observer先启动*
168177 _appTimer.Start();
169178 appObserver.Start();
170删除: _webServer.Start();
179新增: if (config.General.IsWebEnabled)
180新增: {
181新增: _webServer.Start();
182新增: }
171183 }
172184 public void Stop()
173185 {
@@ -218,6 +230,8 @@ namespace Core.Servicers.Instances
218230 // 进入睡眠状态
219231 Debug.WriteLine("进入睡眠状态");
220232
233新增: // 通知sokcet客户端
234新增: _webServer.SendMsg("sleep");
221235 // 停止服务
222236 Stop();
223237
@@ -228,6 +242,9 @@ namespace Core.Servicers.Instances
228242 {
229243 // 从睡眠状态唤醒
230244 Debug.WriteLine("从睡眠状态唤醒");
245新增:
246新增: _webServer.SendMsg("wake");
247新增:
231248 Start();
232249 }
233250 }
@@ -369,6 +386,15 @@ namespace Core.Servicers.Instances
369386 {
370387 return;
371388 }
389新增:
390新增: if (config.General.IsWebEnabled)
391新增: {
392新增: _webServer.Start();
393新增: }
394新增: else
395新增: {
396新增: _webServer.Stop();
397新增: }
372398 }
373399 #endregion
374400
@@ -400,5 +426,33 @@ namespace Core.Servicers.Instances
400426 }
401427 }
402428
429新增: #region 浏览器记录
430新增: private void WebSocketEvent_OnWebLog(Models.WebPage.NotifyWeb args)
431新增: {
432新增: if (_webFilter.IsIgnore(args.Url))
433新增: {
434新增: Debug.WriteLine($"URL已被过滤,{args.Url}");
435新增: return;
436新增: }
437新增:
438新增: // 记录数据
439新增: var site = new Models.WebPage.Site()
440新增: {
441新增: Url = args.Url,
442新增: Title = args.Title
443新增: };
444新增:
445新增: _webData.AddUrlBrowseTime(site, args.Duration, args.ActiveDateTime);
446新增:
447新增: // 处理图标
448新增: Task.Run(async () =>
449新增: {
450新增: string saveName = UrlHelper.GetName(args.Url) + DateTime.Now.ToString("yyyyMM") + ".ico";
451新增: string path = await FaviconDownloader.DownloadAsync(args.Icon, saveName);
452新增: _webData.UpdateUrlFavicon(site, path);
453新增: });
454新增:
455新增: }
456新增: #endregion
403457 }
404458}
修改Core/Servicers/Instances/Sleepdiscover.cs+3 −1看文件
@@ -73,6 +73,7 @@ namespace Core.Servicers.Instances
7373 StopTimer();
7474 timer = new DispatcherTimer();
7575 timer.Interval = new TimeSpan(0, 0, 10);
76新增: //timer.Interval = new TimeSpan(0, 5, 0);
7677 timer.Tick += Timer_Tick;
7778 timer.Start();
7879 }
@@ -223,6 +224,7 @@ namespace Core.Servicers.Instances
223224
224225 private async void Timer_Tick(object sender, EventArgs e)
225226 {
227新增: Debug.WriteLine("检测");
226228 timer.Stop();
227229 bool isSleep = await IsSleepAsync();
228230 if (isSleep)
@@ -369,7 +371,7 @@ namespace Core.Servicers.Instances
369371 {
370372 TimeSpan timeSpan = DateTime.Now - pressKeyboardLastTime;
371373#if DEBUG
372删除: //return timeSpan.TotalSeconds >= 10;
374新增: return timeSpan.TotalSeconds >= 10;
373375#endif
374376 return timeSpan.TotalMinutes >= 10;
375377 }
删除Core/Servicers/Instances/VivaldiBrowserWatch.cs+0 −219
@@ -1,219 +0,0 @@
1删除:using Core.Enums;
2删除:using Core.Event;
3删除:using Core.Librarys;
4删除:using Core.Librarys.Browser.Favicon;
5删除:using Core.Models.WebPage;
6删除:using Core.Servicers.Interfaces;
7删除:using NPOI.SS.Formula.Functions;
8删除:using System;
9删除:using System.Collections.Generic;
10删除:using System.Data.SQLite;
11删除:using System.Diagnostics;
12删除:using System.IO;
13删除:using System.Linq;
14删除:using System.Security.Cryptography;
15删除:using System.Text;
16删除:using System.Threading.Tasks;
17删除:using System.Windows.Automation;
18删除:using System.Windows.Interop;
19删除:using UIAutomationClient;
20删除:
21删除:namespace Core.Servicers.Instances
22删除:{
23删除: public class VivaldiBrowserWatch : IBrowserWatcher
24删除: {
25删除: public event BrowserObserverEventHandler OnSiteChanged;
26删除: private string url, title;
27删除: CUIAutomation automation;
28删除: // 根元素(监听站点切换使用)
29删除: IUIAutomationElement rootElement;
30删除: // 主元素(寻找URL使用)
31删除: IUIAutomationElement mainElement;
32删除: // 站点切换事件
33删除: AutomationPropertyChangedEventHandler siteChangedEventHandler;
34删除:
35删除: public VivaldiBrowserWatch()
36删除: {
37删除: automation = new CUIAutomation();
38删除: siteChangedEventHandler = new AutomationPropertyChangedEventHandler(OnNameChanged);
39删除: }
40删除:
41删除: public void StartWatch(IntPtr handle)
42删除: {
43删除: try
44删除: {
45删除: if (handle == IntPtr.Zero)
46删除: {
47删除: throw new Exception("未传入浏览器句柄");
48删除: }
49删除:
50删除: Win32API.GetWindowThreadProcessId(handle, out int processID);
51删除: Process process = Process.GetProcessById(processID);
52删除: if (process == null)
53删除: {
54删除: return;
55删除: }
56删除:
57删除: Debug.WriteLine("启动浏览器监听,目标:" + process.ProcessName);
58删除: // 搜索根元素
59删除: rootElement = automation.ElementFromHandle(handle);
60删除: if (rootElement == null)
61删除: {
62删除: throw new Exception("找不到根元素!");
63删除: }
64删除: // 找到窗口
65删除: var condtionPanel = automation.CreatePropertyCondition(30003, 50033);
66删除: var condtionName = automation.CreatePropertyCondition(30005, "Chrome_WidgetWin_1");
67删除: var condtionFindWindow = automation.CreateAndCondition(condtionPanel, condtionName);
68删除: var window = rootElement.FindFirst(TreeScope.TreeScope_Children, condtionFindWindow);
69删除: if (window != null)
70删除: {
71删除: // 第二个窗口
72删除: mainElement = window.FindFirst(TreeScope.TreeScope_Children, automation.CreateTrueCondition());
73删除: }
74删除: else
75删除: {
76删除: mainElement = rootElement;
77删除: Debug.WriteLine("没有找到主窗口,使用根元素作为主元素");
78删除: }
79删除:
80删除:
81删除: if (mainElement == null)
82删除: {
83删除: throw new Exception("找不到主元素!");
84删除: }
85删除:
86删除: // 注册事件
87删除: IUIAutomationCacheRequest cacheRequest = automation.CreateCacheRequest();
88删除: cacheRequest.AddProperty(30005);
89删除: int[] props = { 30005 };
90删除:
91删除: automation.AddPropertyChangedEventHandler(rootElement, TreeScope.TreeScope_Element, cacheRequest, siteChangedEventHandler, props);
92删除: Debug.WriteLine("启动浏览器监听成功");
93删除:
94删除: Handle(process.MainWindowTitle);
95删除: }
96删除: catch (Exception e)
97删除: {
98删除: Logger.Error(e.ToString());
99删除: }
100删除: }
101删除:
102删除: private void OnNameChanged(IUIAutomationElement s, int p, object v)
103删除: {
104删除: Handle(v.ToString());
105删除: }
106删除:
107删除: #region AutomationPropertyChangedEventHandler
108删除: private class AutomationPropertyChangedEventHandler : IUIAutomationPropertyChangedEventHandler
109删除: {
110删除: public AutomationPropertyChangedEventHandler(Action<IUIAutomationElement, int, object> action)
111删除: {
112删除: if (action == null)
113删除: throw new ArgumentNullException(nameof(action));
114删除:
115删除: Action = action;
116删除: }
117删除:
118删除: public Action<IUIAutomationElement, int, object> Action { get; }
119删除: public void HandlePropertyChangedEvent(IUIAutomationElement sender, int propertyId, object newValue) => Action(sender, propertyId, newValue);
120删除: }
121删除: #endregion
122删除:
123删除: public void StopWatch()
124删除: {
125删除: try
126删除: {
127删除: Debug.WriteLine("已停止浏览器监听");
128删除: automation.RemovePropertyChangedEventHandler(rootElement, siteChangedEventHandler);
129删除: }
130删除: catch (Exception e)
131删除: {
132删除: Logger.Error(e.ToString());
133删除: }
134删除: }
135删除:
136删除: private string FormatTitle(string title)
137删除: {
138删除: if (string.IsNullOrEmpty(title))
139删除: {
140删除: return title;
141删除: }
142删除: int length = title.LastIndexOf('-') - 1;
143删除: if (length < 1)
144删除: {
145删除: length = 1;
146删除: }
147删除:
148删除: return title.Substring(0, length);
149删除: }
150删除:
151删除: private async void Handle(string title)
152删除: {
153删除: title = FormatTitle(title);
154删除: //Debug.WriteLine($"切换标题 {title}");
155删除: Site site = null;
156删除: if (!string.IsNullOrEmpty(title))
157删除: {
158删除: site = SiteCache.Get(title);
159删除: }
160删除:
161删除: if (site == null)
162删除: {
163删除: string url = await GetURLSync();
164删除: site = new Site()
165删除: {
166删除: Url = url,
167删除: Title = title
168删除: };
169删除: SiteCache.Set(title, url);
170删除: }
171删除:
172删除: ResponseEvent(site.Url, site.Title);
173删除: }
174删除:
175删除: #region 获取浏览器当前URL
176删除: /// <summary>
177删除: /// 获取浏览器当前URL
178删除: /// </summary>
179删除: /// <returns></returns>
180删除: private async Task<string> GetURLSync()
181删除: {
182删除: return await Task.Run(() =>
183删除: {
184删除: string result = string.Empty;
185删除: try
186删除: {
187删除: var condtionEdit = automation.CreatePropertyCondition(30003, 50004);
188删除: var condtionName = automation.CreatePropertyCondition(30011, "urlFieldInput");
189删除: var addressElement = rootElement.FindFirst(TreeScope.TreeScope_Subtree, condtionName);
190删除: if (addressElement != null)
191删除: {
192删除: result = ((IUIAutomationValuePattern)addressElement.GetCurrentPattern(10002)).CurrentValue;
193删除: }
194删除: }
195删除: catch (Exception e)
196删除: {
197删除: Logger.Error(e.ToString());
198删除: }
199删除: return result;
200删除: });
201删除:
202删除: }
203删除: #endregion
204删除:
205删除: private void ResponseEvent(string url, string title)
206删除: {
207删除: if (url != this.url)
208删除: {
209删除: this.url = url;
210删除: this.title = title;
211删除: OnSiteChanged?.Invoke(BrowserType.Vivaldi, new Models.WebPage.Site()
212删除: {
213删除: Url = url,
214删除: Title = title
215删除: });
216删除: }
217删除: }
218删除: }
219删除:}
修改Core/Servicers/Instances/WebFilter.cs+6 −1看文件
@@ -15,7 +15,7 @@ namespace Core.Servicers.Instances
1515 private readonly IAppConfig _appConfig;
1616 private List<string> _ignoreURLCache;
1717 // 默认忽略的规则
18删除: private readonly string[] _ignoreRegexArr = { "^chrome://(.*)", "^edge://(.*)" };
18新增: private readonly string[] _ignoreRegexArr = { "^chrome://(.*)", "^edge://(.*)", "^view-source:(.*)" };
1919 public WebFilter(IAppConfig appConfig_)
2020 {
2121 _appConfig = appConfig_;
@@ -37,6 +37,11 @@ namespace Core.Servicers.Instances
3737
3838 public bool IsIgnore(string url_)
3939 {
40新增: if (string.IsNullOrEmpty(url_))
41新增: {
42新增: return true;
43新增: }
44新增:
4045 if (_ignoreURLCache.Contains(url_))
4146 {
4247 return true;
新增Core/Servicers/Instances/WebServer.cs+58 −0看文件
@@ -0,0 +1,58 @@
1新增:using Core.Event;
2新增:using Core.Librarys.Browser;
3新增:using Core.Models.WebPage;
4新增:using Core.Servicers.Interfaces;
5新增:using Newtonsoft.Json;
6新增:using System;
7新增:using System.Collections.Generic;
8新增:using System.Diagnostics;
9新增:using System.Linq;
10新增:using System.Net;
11新增:using System.Text;
12新增:using System.Threading.Tasks;
13新增:using WebSocketSharp;
14新增:using WebSocketSharp.Server;
15新增:
16新增:namespace Core.Servicers.Instances
17新增:{
18新增: public class WebServer : WebSocketBehavior, IWebServer
19新增: {
20新增: private WebSocketServer _webSocket;
21新增: private bool _isStart = false;
22新增:
23新增: public void Start()
24新增: {
25新增: if (_isStart) return;
26新增: _webSocket = new WebSocketServer(8908, false);
27新增: _webSocket.AddWebSocketService<WebServer>("/TaiWebSentry");
28新增: _webSocket.Start();
29新增: _isStart = true;
30新增: }
31新增:
32新增: public void Stop()
33新增: {
34新增: if (!_isStart) return;
35新增: _webSocket.Stop();
36新增: _isStart = false;
37新增: }
38新增:
39新增: public void SendMsg(string msg_)
40新增: {
41新增: _webSocket.WebSocketServices.Broadcast(msg_);
42新增: }
43新增:
44新增:
45新增: protected override void OnMessage(MessageEventArgs e)
46新增: {
47新增: try
48新增: {
49新增: var log = JsonConvert.DeserializeObject<NotifyWeb>(e.Data);
50新增: WebSocketEvent.Invoke(log);
51新增: }
52新增: catch
53新增: {
54新增:
55新增: }
56新增: }
57新增: }
58新增:}
删除Core/Servicers/Interfaces/IBrowserObserver.cs+0 −29
@@ -1,29 +0,0 @@
1删除:using Core.Event;
2删除:using System;
3删除:using System.Collections.Generic;
4删除:using System.Linq;
5删除:using System.Text;
6删除:using System.Threading.Tasks;
7删除:
8删除:namespace Core.Servicers.Interfaces
9删除:{
10删除: /// <summary>
11删除: /// 浏览器观察服务
12删除: /// </summary>
13删除: public interface IBrowserObserver
14删除: {
15删除: /// <summary>
16删除: /// 启动观察
17删除: /// </summary>
18删除: void Start();
19删除: /// <summary>
20删除: /// 停止观察
21删除: /// </summary>
22删除: void Stop();
23删除:
24删除: /// <summary>
25删除: /// 站点切换时发生
26删除: /// </summary>
27删除: event BrowserObserverEventHandler OnSiteChanged;
28删除: }
29删除:}
改名Core/Servicers/Interfaces/IBrowserWatcher.cs → Core/Servicers/Interfaces/IWebServer.cs+4 −4看文件
@@ -7,10 +7,10 @@ using System.Threading.Tasks;
77
88namespace Core.Servicers.Interfaces
99{
10删除: public interface IBrowserWatcher
10新增: public interface IWebServer
1111 {
12删除: event BrowserObserverEventHandler OnSiteChanged;
13删除: void StartWatch(IntPtr handle);
14删除: void StopWatch();
12新增: void Start();
13新增: void Stop();
14新增: void SendMsg(string msg_);
1515 }
1616}
修改Core/packages.config+1 −0看文件
@@ -20,4 +20,5 @@
2020 <package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net461" />
2121 <package id="System.ValueTuple" version="4.3.0" targetFramework="net461" />
2222 <package id="TaskScheduler" version="2.10.1" targetFramework="net461" />
23新增: <package id="WebSocketSharp" version="1.0.3-rc11" targetFramework="net461" />
2324</packages>
文件末尾没有换行
修改TaiBug/App.config+3 −3看文件
@@ -1,6 +1,6 @@
1删除:<?xml version="1.0" encoding="utf-8" ?>
1新增:<?xml version="1.0" encoding="utf-8"?>
22<configuration>
33 <startup>
4删除: <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
4新增: <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
55 </startup>
6删除:</configuration>
文件末尾没有换行
6新增:</configuration>
修改TaiBug/Properties/Resources.Designer.cs+24 −32看文件
@@ -1,69 +1,61 @@
11//------------------------------------------------------------------------------
22// <auto-generated>
33// 此代码由工具生成。
4删除:// 运行时版本: 4.0.30319.42000
4新增:// 运行时版本:4.0.30319.42000
55//
6删除:// 对此文件的更改可能导致不正确的行为,如果
7删除:// 重新生成代码,则所做更改将丢失。
6新增:// 对此文件的更改可能会导致不正确的行为,并且如果
7新增:// 重新生成代码,这些更改将会丢失。
88// </auto-generated>
99//------------------------------------------------------------------------------
1010
11删除:namespace TaiBug.Properties
12删除:{
13删除:
14删除:
11新增:namespace TaiBug.Properties {
12新增: using System;
13新增:
14新增:
1515 /// <summary>
16删除: /// 强类型资源类,用于查找本地化字符串等。
16新增: /// 一个强类型的资源类,用于查找本地化的字符串等。
1717 /// </summary>
1818 // 此类是由 StronglyTypedResourceBuilder
1919 // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
20删除: // 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen
20新增: // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
2121 // (以 /str 作为命令选项),或重新生成 VS 项目。
22删除: [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
22新增: [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
2323 [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
2424 [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25删除: internal class Resources
26删除: {
27删除:
25新增: internal class Resources {
26新增:
2827 private static global::System.Resources.ResourceManager resourceMan;
29删除:
28新增:
3029 private static global::System.Globalization.CultureInfo resourceCulture;
31删除:
30新增:
3231 [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33删除: internal Resources()
34删除: {
32新增: internal Resources() {
3533 }
36删除:
34新增:
3735 /// <summary>
38删除: /// 返回此类使用的缓存 ResourceManager 实例。
36新增: /// 返回此类使用的缓存的 ResourceManager 实例。
3937 /// </summary>
4038 [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41删除: internal static global::System.Resources.ResourceManager ResourceManager
42删除: {
43删除: get
44删除: {
45删除: if ((resourceMan == null))
46删除: {
39新增: internal static global::System.Resources.ResourceManager ResourceManager {
40新增: get {
41新增: if (object.ReferenceEquals(resourceMan, null)) {
4742 global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TaiBug.Properties.Resources", typeof(Resources).Assembly);
4843 resourceMan = temp;
4944 }
5045 return resourceMan;
5146 }
5247 }
53删除:
48新增:
5449 /// <summary>
5550 /// 重写当前线程的 CurrentUICulture 属性,对
5651 /// 使用此强类型资源类的所有资源查找执行重写。
5752 /// </summary>
5853 [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59删除: internal static global::System.Globalization.CultureInfo Culture
60删除: {
61删除: get
62删除: {
54新增: internal static global::System.Globalization.CultureInfo Culture {
55新增: get {
6356 return resourceCulture;
6457 }
65删除: set
66删除: {
58新增: set {
6759 resourceCulture = value;
6860 }
6961 }
修改TaiBug/Properties/Settings.Designer.cs+13 −17看文件
@@ -1,28 +1,24 @@
11//------------------------------------------------------------------------------
22// <auto-generated>
3删除:// This code was generated by a tool.
4删除:// Runtime Version:4.0.30319.42000
3新增:// 此代码由工具生成。
4新增:// 运行时版本:4.0.30319.42000
55//
6删除:// Changes to this file may cause incorrect behavior and will be lost if
7删除:// the code is regenerated.
6新增:// 对此文件的更改可能会导致不正确的行为,并且如果
7新增:// 重新生成代码,这些更改将会丢失。
88// </auto-generated>
99//------------------------------------------------------------------------------
1010
11删除:namespace TaiBug.Properties
12删除:{
13删除:
14删除:
11新增:namespace TaiBug.Properties {
12新增:
13新增:
1514 [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16删除: [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17删除: internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18删除: {
19删除:
15新增: [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.7.0.0")]
16新增: internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17新增:
2018 private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21删除:
22删除: public static Settings Default
23删除: {
24删除: get
25删除: {
19新增:
20新增: public static Settings Default {
21新增: get {
2622 return defaultInstance;
2723 }
2824 }
修改TaiBug/TaiBug.csproj+2 −1看文件
@@ -8,11 +8,12 @@
88 <OutputType>WinExe</OutputType>
99 <RootNamespace>TaiBug</RootNamespace>
1010 <AssemblyName>TaiBug</AssemblyName>
11删除: <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
11新增: <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
1212 <FileAlignment>512</FileAlignment>
1313 <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
1414 <WarningLevel>4</WarningLevel>
1515 <Deterministic>true</Deterministic>
16新增: <TargetFrameworkProfile />
1617 </PropertyGroup>
1718 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
1819 <PlatformTarget>AnyCPU</PlatformTarget>
修改UI/App.config+10 −10看文件
@@ -1,25 +1,25 @@
1删除:<?xml version="1.0" encoding="utf-8"?>
1新增:<?xml version="1.0" encoding="utf-8"?>
22<configuration>
33 <startup>
4删除: <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
4新增: <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
55 </startup>
66 <runtime>
77 <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
88 <dependentAssembly>
9删除: <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
10删除: <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
9新增: <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
10新增: <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0"/>
1111 </dependentAssembly>
1212 <dependentAssembly>
13删除: <assemblyIdentity name="System.Data.SQLite" publicKeyToken="db937bc2d44ff139" culture="neutral" />
14删除: <bindingRedirect oldVersion="0.0.0.0-1.0.115.5" newVersion="1.0.115.5" />
13新增: <assemblyIdentity name="System.Data.SQLite" publicKeyToken="db937bc2d44ff139" culture="neutral"/>
14新增: <bindingRedirect oldVersion="0.0.0.0-1.0.115.5" newVersion="1.0.115.5"/>
1515 </dependentAssembly>
1616 <dependentAssembly>
17删除: <assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
18删除: <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
17新增: <assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral"/>
18新增: <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0"/>
1919 </dependentAssembly>
2020 <dependentAssembly>
21删除: <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
22删除: <bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" />
21新增: <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral"/>
22新增: <bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1"/>
2323 </dependentAssembly>
2424 </assemblyBinding>
2525 </runtime>
修改UI/Properties/Settings.Designer.cs+1 −1看文件
@@ -12,7 +12,7 @@ namespace UI.Properties {
1212
1313
1414 [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15删除: [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.0.3.0")]
15新增: [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.7.0.0")]
1616 internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
1717
1818 private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
修改UI/Themes/SettingPanel/SettingPanelItem.xaml+1 −1看文件
@@ -31,7 +31,7 @@
3131
3232 </StackPanel>
3333 <base:View Value="{TemplateBinding Description}" Condition="not empty">
34删除: <TextBlock Text="{TemplateBinding Description}" FontSize="12" Margin="0,4,0,0" Foreground="{DynamicResource SubTextBrush}" VerticalAlignment="Center"/>
34新增: <TextBlock Text="{TemplateBinding Description}" FontSize="12" Margin="0,4,0,0" Foreground="{DynamicResource SubTextBrush}" VerticalAlignment="Center" TextWrapping="WrapWithOverflow"/>
3535 </base:View>
3636 </StackPanel>
3737 </Grid>
修改UI/UI.csproj+2 −1看文件
@@ -8,7 +8,7 @@
88 <OutputType>WinExe</OutputType>
99 <RootNamespace>UI</RootNamespace>
1010 <AssemblyName>Tai</AssemblyName>
11删除: <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
11新增: <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
1212 <FileAlignment>512</FileAlignment>
1313 <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
1414 <WarningLevel>4</WarningLevel>
@@ -117,6 +117,7 @@
117117 <Reference Include="System.Xaml">
118118 <RequiredTargetFramework>4.0</RequiredTargetFramework>
119119 </Reference>
120新增: <Reference Include="websocket-sharp, Version=1.0.2.59611, Culture=neutral, PublicKeyToken=5660b08a1845a91e" />
120121 <Reference Include="WindowsBase" />
121122 <Reference Include="PresentationCore" />
122123 <Reference Include="PresentationFramework" />
修改Updater/App.config+3 −3看文件
@@ -1,6 +1,6 @@
1删除:<?xml version="1.0" encoding="utf-8" ?>
1新增:<?xml version="1.0" encoding="utf-8"?>
22<configuration>
33 <startup>
4删除: <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
4新增: <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
55 </startup>
6删除:</configuration>
文件末尾没有换行
6新增:</configuration>
修改Updater/Properties/Resources.Designer.cs+24 −32看文件
@@ -1,69 +1,61 @@
11//------------------------------------------------------------------------------
22// <auto-generated>
33// 此代码由工具生成。
4删除:// 运行时版本: 4.0.30319.42000
4新增:// 运行时版本:4.0.30319.42000
55//
6删除:// 对此文件的更改可能导致不正确的行为,如果
7删除:// 重新生成代码,则所做更改将丢失。
6新增:// 对此文件的更改可能会导致不正确的行为,并且如果
7新增:// 重新生成代码,这些更改将会丢失。
88// </auto-generated>
99//------------------------------------------------------------------------------
1010
11删除:namespace Updater.Properties
12删除:{
13删除:
14删除:
11新增:namespace Updater.Properties {
12新增: using System;
13新增:
14新增:
1515 /// <summary>
16删除: /// 强类型资源类,用于查找本地化字符串等。
16新增: /// 一个强类型的资源类,用于查找本地化的字符串等。
1717 /// </summary>
1818 // 此类是由 StronglyTypedResourceBuilder
1919 // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
20删除: // 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen
20新增: // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
2121 // (以 /str 作为命令选项),或重新生成 VS 项目。
22删除: [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
22新增: [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
2323 [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
2424 [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25删除: internal class Resources
26删除: {
27删除:
25新增: internal class Resources {
26新增:
2827 private static global::System.Resources.ResourceManager resourceMan;
29删除:
28新增:
3029 private static global::System.Globalization.CultureInfo resourceCulture;
31删除:
30新增:
3231 [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33删除: internal Resources()
34删除: {
32新增: internal Resources() {
3533 }
36删除:
34新增:
3735 /// <summary>
38删除: /// 返回此类使用的缓存 ResourceManager 实例。
36新增: /// 返回此类使用的缓存的 ResourceManager 实例。
3937 /// </summary>
4038 [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41删除: internal static global::System.Resources.ResourceManager ResourceManager
42删除: {
43删除: get
44删除: {
45删除: if ((resourceMan == null))
46删除: {
39新增: internal static global::System.Resources.ResourceManager ResourceManager {
40新增: get {
41新增: if (object.ReferenceEquals(resourceMan, null)) {
4742 global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Updater.Properties.Resources", typeof(Resources).Assembly);
4843 resourceMan = temp;
4944 }
5045 return resourceMan;
5146 }
5247 }
53删除:
48新增:
5449 /// <summary>
5550 /// 重写当前线程的 CurrentUICulture 属性,对
5651 /// 使用此强类型资源类的所有资源查找执行重写。
5752 /// </summary>
5853 [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59删除: internal static global::System.Globalization.CultureInfo Culture
60删除: {
61删除: get
62删除: {
54新增: internal static global::System.Globalization.CultureInfo Culture {
55新增: get {
6356 return resourceCulture;
6457 }
65删除: set
66删除: {
58新增: set {
6759 resourceCulture = value;
6860 }
6961 }
修改Updater/Properties/Settings.Designer.cs+13 −17看文件
@@ -1,28 +1,24 @@
11//------------------------------------------------------------------------------
22// <auto-generated>
3删除:// This code was generated by a tool.
4删除:// Runtime Version:4.0.30319.42000
3新增:// 此代码由工具生成。
4新增:// 运行时版本:4.0.30319.42000
55//
6删除:// Changes to this file may cause incorrect behavior and will be lost if
7删除:// the code is regenerated.
6新增:// 对此文件的更改可能会导致不正确的行为,并且如果
7新增:// 重新生成代码,这些更改将会丢失。
88// </auto-generated>
99//------------------------------------------------------------------------------
1010
11删除:namespace Updater.Properties
12删除:{
13删除:
14删除:
11新增:namespace Updater.Properties {
12新增:
13新增:
1514 [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16删除: [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17删除: internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18删除: {
19删除:
15新增: [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.7.0.0")]
16新增: internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17新增:
2018 private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21删除:
22删除: public static Settings Default
23删除: {
24删除: get
25删除: {
19新增:
20新增: public static Settings Default {
21新增: get {
2622 return defaultInstance;
2723 }
2824 }
修改Updater/Updater.csproj+2 −1看文件
@@ -8,11 +8,12 @@
88 <OutputType>WinExe</OutputType>
99 <RootNamespace>Updater</RootNamespace>
1010 <AssemblyName>Updater</AssemblyName>
11删除: <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
11新增: <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
1212 <FileAlignment>512</FileAlignment>
1313 <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
1414 <WarningLevel>4</WarningLevel>
1515 <Deterministic>true</Deterministic>
16新增: <TargetFrameworkProfile />
1617 </PropertyGroup>
1718 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
1819 <PlatformTarget>AnyCPU</PlatformTarget>
新增WebExtensions/Chrome/icons/socket-active.png看文件

二进制文件,不显示改动。

新增WebExtensions/Chrome/icons/socket-inactive.png看文件

二进制文件,不显示改动。

新增WebExtensions/Chrome/manifest.json+17 −0看文件
@@ -0,0 +1,17 @@
1新增:{
2新增: "name": "Tai Sentry",
3新增: "description": "Tai网页浏览数据统计拓展",
4新增: "version": "0.1",
5新增: "manifest_version": 3,
6新增: "minimum_chrome_version": "116",
7新增: "action": {
8新增: "default_icon": "icons/socket-inactive.png"
9新增: },
10新增: "background": {
11新增: "service_worker": "service-worker.js",
12新增: "type": "module"
13新增: },
14新增: "permissions": [
15新增: "tabs"
16新增: ]
17新增:}
文件末尾没有换行
新增WebExtensions/Chrome/service-worker.js+318 −0看文件
@@ -0,0 +1,318 @@
1新增:// ws心跳间隔
2新增:const TEN_SECONDS_MS = 10 * 1000;
3新增:// 焦点检测间隔
4新增:const FOCUSED_CHECK_MS = 1000;
5新增:// 自动重新通知间隔
6新增:const RENOTIFY_MS = 10 * 1000;
7新增:// 重连失败次数进入睡眠状态
8新增:const RECONNECTFAIL_SLEEP = 5;
9新增:// Tai WS服务器URL
10新增:const WSURL = 'ws://127.0.0.1:8908/TaiWebSentry';
11新增:
12新增:let webSocket = null;
13新增:let isConnected = false;
14新增:let isChromeFocused = true;
15新增:let autoReConnectIntervalId = null;
16新增:// 是否处于睡眠状态(来源Tai通知)
17新增:let isSleep = false;
18新增:// 焦点网页数据
19新增:let activePage = {
20新增: url: '',
21新增: title: '',
22新增: icon: '',
23新增: startTime: '',
24新增: endTime: '',
25新增: duration: 0
26新增:};
27新增:// 重连失败次数
28新增:let reconnectFail = 0;
29新增:
30新增:init();
31新增:
32新增:/**
33新增: * 初始化插件(入口
34新增: */
35新增:function init() {
36新增: connect();
37新增: startWatchFocus();
38新增: startRenofity();
39新增:}
40新增:
41新增:/**
42新增: * 连接Tai
43新增: */
44新增:function connect() {
45新增: webSocket = new WebSocket(WSURL);
46新增: webSocket.onopen = (event) => {
47新增: isConnected = true;
48新增: isSleep = false;
49新增: reconnectFail = 0;
50新增: clearInterval(autoReConnectIntervalId);
51新增: chrome.action.setIcon({ path: 'icons/socket-active.png' });
52新增: keepAlive();
53新增: console.log("已连接Tai!");
54新增: };
55新增: webSocket.onmessage = (event) => {
56新增: console.log(event.data);
57新增: if (event.data === 'sleep') {
58新增: isSleep = true;
59新增: calDuration();
60新增: console.log("睡眠");
61新增: }
62新增: else if (event.data === 'wake') {
63新增: isSleep = false;
64新增: console.log("唤醒");
65新增: }
66新增:
67新增: };
68新增: webSocket.onclose = (event) => {
69新增: isConnected = false;
70新增: chrome.action.setIcon({ path: 'icons/socket-inactive.png' });
71新增: console.warn('与Tai失去连接...');
72新增: webSocket = null;
73新增: startAutoReConnect();
74新增: };
75新增:}
76新增:
77新增:function disconnect() {
78新增: if (isConnected && webSocket) {
79新增: webSocket.close();
80新增: isConnected = false;
81新增: }
82新增:}
83新增:
84新增:function startAutoReConnect() {
85新增: clearInterval(autoReConnectIntervalId);
86新增: autoReConnectIntervalId = setInterval(
87新增: () => {
88新增: if (!isConnected) {
89新增: console.log("尝试重新连接Tai...")
90新增: connect();
91新增: reconnectFail++;
92新增: // 达到重连失败阈值时进入睡眠状态
93新增: if (reconnectFail >= RECONNECTFAIL_SLEEP && !isSleep) {
94新增: isSleep = true;
95新增: }
96新增: }
97新增: },
98新增: TEN_SECONDS_MS
99新增: );
100新增:}
101新增:
102新增:/**
103新增: * 保持心跳,防止插件掉线
104新增: */
105新增:function keepAlive() {
106新增: const keepAliveIntervalId = setInterval(
107新增: () => {
108新增: if (isConnected && webSocket) {
109新增: console.log('ping');
110新增: webSocket.send('ping');
111新增: } else {
112新增: clearInterval(keepAliveIntervalId);
113新增: }
114新增: },
115新增: // It's important to pick an interval that's shorter than 30s, to
116新增: // avoid that the service worker becomes inactive.
117新增: TEN_SECONDS_MS
118新增: );
119新增:}
120新增:
121新增:
122新增:// Chrome functions
123新增:
124新增:// 监听Chrome选项卡切换事件
125新增:chrome.tabs.onActivated.addListener(async function
126新增: (e) {
127新增: const tab = await getTab(e.tabId);
128新增: onActivePage(tab);
129新增:}
130新增:);
131新增:
132新增:// 监听Chrome选项卡更新事件
133新增:chrome.tabs.onUpdated.addListener(function
134新增: (tabId, changeInfo, tab) {
135新增: if (changeInfo.status == 'complete' && tab.active) {
136新增: onActivePage(tab);
137新增: }
138新增:}
139新增:);
140新增:
141新增:/**
142新增: * 通过TabId获取Tab
143新增: * @param {Number} tabId TabId
144新增: * @returns Tab
145新增: */
146新增:function getTab(tabId) {
147新增: return new Promise((resolve, reject) => {
148新增: chrome.tabs.get(
149新增: tabId,
150新增: function (e) {
151新增: resolve(e);
152新增: }
153新增: )
154新增: });
155新增:}
156新增:
157新增:/**
158新增: * 指示当前浏览器是否处于焦点中
159新增: * @returns 焦点中返回true
160新增: */
161新增:function isFocused() {
162新增: return new Promise((resolve, reject) => {
163新增: chrome.windows.getCurrent(function (w) {
164新增: resolve(w.focused);
165新增: });
166新增: });
167新增:
168新增:}
169新增:
170新增:/**
171新增: * 获取当前焦点Tab
172新增: * @returns Tab Obj
173新增: */
174新增:function getCurrentTab() {
175新增: return new Promise((resolve, reject) => {
176新增: chrome.tabs.query({ active: true }, function (tab) {
177新增: if (tab && tab.length > 0) {
178新增: resolve(tab[0]);
179新增: }
180新增: else {
181新增: reject(tab);
182新增: }
183新增: });
184新增: });
185新增:}
186新增:
187新增:
188新增:// Tai functions
189新增:
190新增:// 通知失败的集合
191新增:let notifyFailList = [];
192新增:
193新增:/**
194新增: * 重新发送通知失败的数据(最早的一条)
195新增: */
196新增:function renotify() {
197新增: if (isConnected && webSocket && notifyFailList.length > 0) {
198新增: const item = notifyFailList[0];
199新增: notifyFailList.splice(0, 1);
200新增: notifyTai(item);
201新增: }
202新增:}
203新增:
204新增:/**
205新增: * 通知Tai更新数据
206新增: * @param {*} data 统计数据
207新增: */
208新增:function notifyTai(data = {
209新增: Url,
210新增: Title,
211新增: Icon,
212新增: Duration,
213新增: ActiveTime
214新增:}) {
215新增: console.log("notify", data);
216新增: if (isConnected && webSocket) {
217新增: webSocket.send(JSON.stringify(data));
218新增: }
219新增: else {
220新增: // let item = notifyFailList.find(s => s.Url === data.Url);
221新增: // if (item) {
222新增: // item.Duration += data.Duration;
223新增: // }
224新增: // else {
225新增: notifyFailList.push(data);
226新增: // }
227新增:
228新增: console.log("failList", notifyFailList)
229新增: }
230新增:}
231新增:
232新增:/**
233新增: * 响应网页焦点切换
234新增: * @param {ChromeTab} tab Tab
235新增: */
236新增:function onActivePage(tab) {
237新增: // 睡眠状态不处理
238新增: if (isSleep) return;
239新增:
240新增: if (activePage && activePage.url) {
241新增: if (activePage.url !== tab.url) {
242新增: // 统计时间
243新增: calDuration();
244新增: setActive(tab);
245新增: }
246新增: }
247新增: else {
248新增: setActive(tab);
249新增: }
250新增:}
251新增:
252新增:/**
253新增: * 设置当前焦点网页数据
254新增: * @param {*} tab Tab
255新增: */
256新增:function setActive(tab) {
257新增: const { url, title, favIconUrl: icon } = tab;
258新增: if (url) {
259新增: activePage = {
260新增: url, title, icon, startTime: new Date().getTime()
261新增: };
262新增: }
263新增: else {
264新增: activePage = null;
265新增: }
266新增:}
267新增:
268新增:/**
269新增: * 计算并通知焦点网页浏览时长
270新增: */
271新增:function calDuration() {
272新增: if (activePage && activePage.url) {
273新增: let duration = parseInt((new Date().getTime() - activePage.startTime) / 1000);
274新增: let activeTime = parseInt(activePage.startTime / 1000);
275新增: const { url: Url, title: Title, icon: Icon } = activePage;
276新增: activePage = null;
277新增: notifyTai({ Url, Title, Icon, Duration: duration, ActiveTime: activeTime });
278新增: }
279新增:}
280新增:
281新增:/**
282新增: * 启动焦点监听(用于检测用户是否处于浏览器中
283新增: */
284新增:function startWatchFocus() {
285新增: console.log("开始监听焦点");
286新增: setInterval(
287新增: async () => {
288新增: const focused = await isFocused();
289新增: if (focused) {
290新增: if (!isChromeFocused) {
291新增: isChromeFocused = true;
292新增: // 重置统计
293新增: const tab = await getCurrentTab();
294新增: onActivePage(tab);
295新增: console.warn("重置统计")
296新增: }
297新增: }
298新增: else {
299新增: if (isChromeFocused) {
300新增: isChromeFocused = false;
301新增: // 更新时间
302新增: calDuration();
303新增: console.warn("更新时间")
304新增: }
305新增: }
306新增: },
307新增: FOCUSED_CHECK_MS
308新增: );
309新增:}
310新增:
311新增:/**
312新增: * 启动定时重新发送失败的数据通知
313新增: */
314新增:function startRenofity() {
315新增: setInterval(() => {
316新增: renotify();
317新增: }, RENOTIFY_MS);
318新增:}
文件末尾没有换行