├── .all-contributorsrc
├── .gitattributes
├── .github
├── FUNDING.yml
└── ISSUE_TEMPLATE
│ └── bug-report-----.md
├── .gitignore
├── LICENSE
├── PixivFSUWP.sln
├── PixivFSUWP
├── App.xaml
├── App.xaml.cs
├── Assets
│ ├── AppLogo.kra
│ ├── GH_64.png
│ ├── LockScreenLogo.scale-200.png
│ ├── LoginBG.jpg
│ ├── PixivHeader.png
│ ├── PixivHeader_L.png
│ ├── PixivText.png
│ ├── PixivText_L.png
│ ├── Pixiv_Logo.svg
│ ├── QQ_64.png
│ ├── SauceNAO.png
│ ├── SplashScreen.scale-200.png
│ ├── Square150x150Logo.scale-200.png
│ ├── Square44x44Logo.scale-200.png
│ ├── Square44x44Logo.targetsize-256_altform-unplated.png
│ ├── Square71x71Logo.scale-200.png
│ └── StoreLogo.png
├── BigImage.xaml
├── BigImage.xaml.cs
├── Controls
│ ├── ImageSelectorPanel.cs
│ ├── Pixiv_Logo.xaml
│ ├── Pixiv_Logo.xaml.cs
│ ├── TagsPanel.cs
│ ├── WaterfallContentPanel.cs
│ └── WaterfallListView.cs
├── Converters
│ ├── BookmarkHeartVisibilityConverter.cs
│ ├── ChildrenCommentVisibilityConverter.cs
│ ├── ContributionsConverter.cs
│ └── MultiPageVisibilityConverter.cs
├── Data
│ ├── Backstack.cs
│ ├── BigImageDetail.cs
│ ├── CacheManager.cs
│ ├── Collections
│ │ ├── BookmarkIllustsCollection.cs
│ │ ├── CommentsCollection.cs
│ │ ├── FollowingIllustsCollection.cs
│ │ ├── RankingIllustsCollection.cs
│ │ ├── RecommendIllustsCollection.cs
│ │ ├── SearchResultIllustsCollection.cs
│ │ └── UserIllustsCollection.cs
│ ├── CommentAvatarLoader.cs
│ ├── Contributor.cs
│ ├── ContributorsHelper.cs
│ ├── CurrentUser.cs
│ ├── DownloadManager.cs
│ ├── IllustCommentItem.cs
│ ├── IllustDetail.cs
│ ├── OverAll.cs
│ ├── Ugoira.cs
│ ├── UgoiraHelper.cs
│ ├── UserDetail.cs
│ └── WaterfallItem.cs
├── DownloadManager.xaml
├── DownloadManager.xaml.cs
├── DownloadingPage.xaml
├── DownloadingPage.xaml.cs
├── IllustDetailPage.xaml
├── IllustDetailPage.xaml.cs
├── Interfaces
│ └── IGoBackFlag.cs
├── LoginPage.xaml
├── LoginPage.xaml.cs
├── MainPage.xaml
├── MainPage.xaml.cs
├── MultilingualResources
│ ├── PixivFSUWP.ja.xlf
│ ├── PixivFSUWP.zh-Hans.xlf
│ └── PixivFSUWP.zh-Hant.xlf
├── Package.appxmanifest
├── PixivFSUWP.csproj
├── PixivFSUWP_TemporaryKey.pfx
├── Properties
│ ├── AssemblyInfo.cs
│ └── Default.rd.xml
├── ReportIssuePage.xaml
├── ReportIssuePage.xaml.cs
├── SearchPage.xaml
├── SearchPage.xaml.cs
├── SettingsPage.xaml
├── SettingsPage.xaml.cs
├── Strings
│ ├── en
│ │ └── Resources.resw
│ ├── ja
│ │ └── Resources.resw
│ ├── zh-Hans
│ │ └── Resources.resw
│ └── zh-Hant
│ │ └── Resources.resw
├── Themes
│ ├── Dark.xaml
│ └── Light.xaml
├── UserDetailPage.xaml
├── UserDetailPage.xaml.cs
├── ViewModels
│ ├── CommentViewModel.cs
│ ├── ContributorViewModel.cs
│ ├── ImageItemViewModel.cs
│ ├── TagViewModel.cs
│ └── WaterfallItemViewModel.cs
├── WaterfallPage.xaml
└── WaterfallPage.xaml.cs
├── README.md
├── Translate.md
├── TroubleShoot.md
├── UpdataLog.md
└── azure-pipelines.yml
/.all-contributorsrc:
--------------------------------------------------------------------------------
1 | {
2 | "files": [
3 | "README.md"
4 | ],
5 | "imageSize": 100,
6 | "commit": false,
7 | "contributors": [
8 | {
9 | "login": "chenxuuu",
10 | "name": "chenxuuu",
11 | "avatar_url": "https://avatars3.githubusercontent.com/u/10357394?v=4",
12 | "profile": "https://www.chenxublog.com/",
13 | "contributions": [
14 | "doc"
15 | ]
16 | },
17 | {
18 | "login": "SakuraSa233",
19 | "name": "逢坂桜",
20 | "avatar_url": "https://avatars1.githubusercontent.com/u/24848528?v=4",
21 | "profile": "https://qaq.jp",
22 | "contributions": [
23 | "translation"
24 | ]
25 | },
26 | {
27 | "login": "TuMIer",
28 | "name": "TuMIer",
29 | "avatar_url": "https://avatars2.githubusercontent.com/u/45781074?v=4",
30 | "profile": "https://github.com/TuMIer",
31 | "contributions": [
32 | "bug"
33 | ]
34 | },
35 | {
36 | "login": "RazeSoldier",
37 | "name": "Raze Soldier",
38 | "avatar_url": "https://avatars0.githubusercontent.com/u/29511518?v=4",
39 | "profile": "http://razesoldier.cn",
40 | "contributions": [
41 | "bug"
42 | ]
43 | },
44 | {
45 | "login": "Funny-ppt",
46 | "name": "Funny-ppt",
47 | "avatar_url": "https://avatars3.githubusercontent.com/u/48616775?v=4",
48 | "profile": "https://github.com/Funny-ppt",
49 | "contributions": [
50 | "bug"
51 | ]
52 | },
53 | {
54 | "login": "dsyo2008",
55 | "name": "dsyo2008",
56 | "avatar_url": "https://avatars2.githubusercontent.com/u/3739056?v=4",
57 | "profile": "https://github.com/dsyo2008",
58 | "contributions": [
59 | "ideas"
60 | ]
61 | },
62 | {
63 | "login": "ZeroSimple",
64 | "name": "Henry He",
65 | "avatar_url": "https://avatars2.githubusercontent.com/u/22572927?v=4",
66 | "profile": "https://github.com/ZeroSimple",
67 | "contributions": [
68 | "bug",
69 | "code"
70 | ]
71 | },
72 | {
73 | "login": "frg2089",
74 | "name": "舰队的偶像-岛风酱!",
75 | "avatar_url": "https://avatars0.githubusercontent.com/u/42184238?v=4",
76 | "profile": "https://github.com/frg2089",
77 | "contributions": [
78 | "code"
79 | ]
80 | },
81 | {
82 | "login": "handsome-yaokun",
83 | "name": "handsome-yaokun",
84 | "avatar_url": "https://avatars1.githubusercontent.com/u/48851792?v=4",
85 | "profile": "https://github.com/handsome-yaokun",
86 | "contributions": [
87 | "bug"
88 | ]
89 | },
90 | {
91 | "login": "Baka632",
92 | "name": "Baka632",
93 | "avatar_url": "https://avatars1.githubusercontent.com/u/48171809?v=4",
94 | "profile": "https://github.com/Baka632",
95 | "contributions": [
96 | "bug"
97 | ]
98 | },
99 | {
100 | "login": "pccanales",
101 | "name": "pccanales",
102 | "avatar_url": "https://avatars3.githubusercontent.com/u/57200458?v=4",
103 | "profile": "https://github.com/pccanales",
104 | "contributions": [
105 | "bug"
106 | ]
107 | },
108 | {
109 | "login": "SLK-xlw",
110 | "name": "SLK-xlw",
111 | "avatar_url": "https://avatars0.githubusercontent.com/u/57425595?v=4",
112 | "profile": "https://github.com/SLK-xlw",
113 | "contributions": [
114 | "bug"
115 | ]
116 | },
117 | {
118 | "login": "Stars-sea",
119 | "name": "Star sea",
120 | "avatar_url": "https://avatars0.githubusercontent.com/u/47738830?v=4",
121 | "profile": "https://github.com/Stars-sea",
122 | "contributions": [
123 | "bug"
124 | ]
125 | },
126 | {
127 | "login": "Feng-Bu-Jue",
128 | "name": "FengBuJue",
129 | "avatar_url": "https://avatars0.githubusercontent.com/u/31085556?v=4",
130 | "profile": "https://github.com/Feng-Bu-Jue",
131 | "contributions": [
132 | "code"
133 | ]
134 | },
135 | {
136 | "login": "lingxd",
137 | "name": "hokori",
138 | "avatar_url": "https://avatars1.githubusercontent.com/u/27987136?v=4",
139 | "profile": "https://www.hokori.cn",
140 | "contributions": [
141 | "bug"
142 | ]
143 | },
144 | {
145 | "login": "YukinoShary",
146 | "name": "Shary0x62",
147 | "avatar_url": "https://avatars0.githubusercontent.com/u/26871617?v=4",
148 | "profile": "https://github.com/YukinoShary",
149 | "contributions": [
150 | "code"
151 | ]
152 | },
153 | {
154 | "login": "ProJend",
155 | "name": "ProJend",
156 | "avatar_url": "https://avatars1.githubusercontent.com/u/55018532?v=4",
157 | "profile": "https://github.com/ProJend",
158 | "contributions": [
159 | "code"
160 | ]
161 | },
162 | {
163 | "login": "Incisakura",
164 | "name": "いんしさくら",
165 | "avatar_url": "https://avatars1.githubusercontent.com/u/24848528?v=4",
166 | "profile": "http://localhost",
167 | "contributions": [
168 | "translation"
169 | ]
170 | }
171 | ],
172 | "contributorsPerLine": 7,
173 | "projectName": "pixivfs-uwp",
174 | "projectOwner": "tobiichiamane",
175 | "repoType": "github",
176 | "repoHost": "https://github.com",
177 | "skipCi": true
178 | }
179 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | ko_fi: communistfish
4 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug-report-----.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report/问题报告
3 | about: Create a report to help us improve/创建一份可以帮助我们的报告
4 | title: ''
5 | labels: bug
6 | assignees: tobiichiamane
7 |
8 | ---
9 |
10 | **Describe the bug/描述你遇到的问题**
11 |
12 | **How to reproduce/复现问题的步骤**
13 |
14 | **Additional information/额外信息**
15 | Please paste the information copied from the app below if you experienced a crash.
16 | 如果您遭遇了崩溃,请将从应用中复制的信息粘贴在下面。
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Dd]ebugPublic/
19 | [Rr]elease/
20 | [Rr]eleases/
21 | x64/
22 | x86/
23 | [Aa][Rr][Mm]/
24 | [Aa][Rr][Mm]64/
25 | bld/
26 | [Bb]in/
27 | [Oo]bj/
28 | [Ll]og/
29 |
30 | # Visual Studio 2015/2017 cache/options directory
31 | .vs/
32 | # Uncomment if you have tasks that create the project's static files in wwwroot
33 | #wwwroot/
34 |
35 | # Visual Studio 2017 auto generated files
36 | Generated\ Files/
37 |
38 | # MSTest test Results
39 | [Tt]est[Rr]esult*/
40 | [Bb]uild[Ll]og.*
41 |
42 | # NUNIT
43 | *.VisualState.xml
44 | TestResult.xml
45 |
46 | # Build Results of an ATL Project
47 | [Dd]ebugPS/
48 | [Rr]eleasePS/
49 | dlldata.c
50 |
51 | # Benchmark Results
52 | BenchmarkDotNet.Artifacts/
53 |
54 | # .NET Core
55 | project.lock.json
56 | project.fragment.lock.json
57 | artifacts/
58 |
59 | # StyleCop
60 | StyleCopReport.xml
61 |
62 | # Files built by Visual Studio
63 | *_i.c
64 | *_p.c
65 | *_h.h
66 | *.ilk
67 | *.meta
68 | *.obj
69 | *.iobj
70 | *.pch
71 | *.pdb
72 | *.ipdb
73 | *.pgc
74 | *.pgd
75 | *.rsp
76 | *.sbr
77 | *.tlb
78 | *.tli
79 | *.tlh
80 | *.tmp
81 | *.tmp_proj
82 | *_wpftmp.csproj
83 | *.log
84 | *.vspscc
85 | *.vssscc
86 | .builds
87 | *.pidb
88 | *.svclog
89 | *.scc
90 |
91 | # Chutzpah Test files
92 | _Chutzpah*
93 |
94 | # Visual C++ cache files
95 | ipch/
96 | *.aps
97 | *.ncb
98 | *.opendb
99 | *.opensdf
100 | *.sdf
101 | *.cachefile
102 | *.VC.db
103 | *.VC.VC.opendb
104 |
105 | # Visual Studio profiler
106 | *.psess
107 | *.vsp
108 | *.vspx
109 | *.sap
110 |
111 | # Visual Studio Trace Files
112 | *.e2e
113 |
114 | # TFS 2012 Local Workspace
115 | $tf/
116 |
117 | # Guidance Automation Toolkit
118 | *.gpState
119 |
120 | # ReSharper is a .NET coding add-in
121 | _ReSharper*/
122 | *.[Rr]e[Ss]harper
123 | *.DotSettings.user
124 |
125 | # JustCode is a .NET coding add-in
126 | .JustCode
127 |
128 | # TeamCity is a build add-in
129 | _TeamCity*
130 |
131 | # DotCover is a Code Coverage Tool
132 | *.dotCover
133 |
134 | # AxoCover is a Code Coverage Tool
135 | .axoCover/*
136 | !.axoCover/settings.json
137 |
138 | # Visual Studio code coverage results
139 | *.coverage
140 | *.coveragexml
141 |
142 | # NCrunch
143 | _NCrunch_*
144 | .*crunch*.local.xml
145 | nCrunchTemp_*
146 |
147 | # MightyMoose
148 | *.mm.*
149 | AutoTest.Net/
150 |
151 | # Web workbench (sass)
152 | .sass-cache/
153 |
154 | # Installshield output folder
155 | [Ee]xpress/
156 |
157 | # DocProject is a documentation generator add-in
158 | DocProject/buildhelp/
159 | DocProject/Help/*.HxT
160 | DocProject/Help/*.HxC
161 | DocProject/Help/*.hhc
162 | DocProject/Help/*.hhk
163 | DocProject/Help/*.hhp
164 | DocProject/Help/Html2
165 | DocProject/Help/html
166 |
167 | # Click-Once directory
168 | publish/
169 |
170 | # Publish Web Output
171 | *.[Pp]ublish.xml
172 | *.azurePubxml
173 | # Note: Comment the next line if you want to checkin your web deploy settings,
174 | # but database connection strings (with potential passwords) will be unencrypted
175 | *.pubxml
176 | *.publishproj
177 |
178 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
179 | # checkin your Azure Web App publish settings, but sensitive information contained
180 | # in these scripts will be unencrypted
181 | PublishScripts/
182 |
183 | # NuGet Packages
184 | *.nupkg
185 | # The packages folder can be ignored because of Package Restore
186 | **/[Pp]ackages/*
187 | # except build/, which is used as an MSBuild target.
188 | !**/[Pp]ackages/build/
189 | # Uncomment if necessary however generally it will be regenerated when needed
190 | #!**/[Pp]ackages/repositories.config
191 | # NuGet v3's project.json files produces more ignorable files
192 | *.nuget.props
193 | *.nuget.targets
194 |
195 | # Microsoft Azure Build Output
196 | csx/
197 | *.build.csdef
198 |
199 | # Microsoft Azure Emulator
200 | ecf/
201 | rcf/
202 |
203 | # Windows Store app package directories and files
204 | AppPackages/
205 | BundleArtifacts/
206 | Package.StoreAssociation.xml
207 | _pkginfo.txt
208 | *.appx
209 |
210 | # Visual Studio cache files
211 | # files ending in .cache can be ignored
212 | *.[Cc]ache
213 | # but keep track of directories ending in .cache
214 | !?*.[Cc]ache/
215 |
216 | # Others
217 | ClientBin/
218 | ~$*
219 | *~
220 | *.dbmdl
221 | *.dbproj.schemaview
222 | *.jfm
223 | *.pfx
224 | *.publishsettings
225 | orleans.codegen.cs
226 |
227 | # Including strong name files can present a security risk
228 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
229 | #*.snk
230 |
231 | # Since there are multiple workflows, uncomment next line to ignore bower_components
232 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
233 | #bower_components/
234 |
235 | # RIA/Silverlight projects
236 | Generated_Code/
237 |
238 | # Backup & report files from converting an old project file
239 | # to a newer Visual Studio version. Backup files are not needed,
240 | # because we have git ;-)
241 | _UpgradeReport_Files/
242 | Backup*/
243 | UpgradeLog*.XML
244 | UpgradeLog*.htm
245 | ServiceFabricBackup/
246 | *.rptproj.bak
247 |
248 | # SQL Server files
249 | *.mdf
250 | *.ldf
251 | *.ndf
252 |
253 | # Business Intelligence projects
254 | *.rdl.data
255 | *.bim.layout
256 | *.bim_*.settings
257 | *.rptproj.rsuser
258 | *- Backup*.rdl
259 |
260 | # Microsoft Fakes
261 | FakesAssemblies/
262 |
263 | # GhostDoc plugin setting file
264 | *.GhostDoc.xml
265 |
266 | # Node.js Tools for Visual Studio
267 | .ntvs_analysis.dat
268 | node_modules/
269 |
270 | # Visual Studio 6 build log
271 | *.plg
272 |
273 | # Visual Studio 6 workspace options file
274 | *.opt
275 |
276 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
277 | *.vbw
278 |
279 | # Visual Studio LightSwitch build output
280 | **/*.HTMLClient/GeneratedArtifacts
281 | **/*.DesktopClient/GeneratedArtifacts
282 | **/*.DesktopClient/ModelManifest.xml
283 | **/*.Server/GeneratedArtifacts
284 | **/*.Server/ModelManifest.xml
285 | _Pvt_Extensions
286 |
287 | # Paket dependency manager
288 | .paket/paket.exe
289 | paket-files/
290 |
291 | # FAKE - F# Make
292 | .fake/
293 |
294 | # JetBrains Rider
295 | .idea/
296 | *.sln.iml
297 |
298 | # CodeRush personal settings
299 | .cr/personal
300 |
301 | # Python Tools for Visual Studio (PTVS)
302 | __pycache__/
303 | *.pyc
304 |
305 | # Cake - Uncomment if you are using it
306 | # tools/**
307 | # !tools/packages.config
308 |
309 | # Tabs Studio
310 | *.tss
311 |
312 | # Telerik's JustMock configuration file
313 | *.jmconfig
314 |
315 | # BizTalk build output
316 | *.btp.cs
317 | *.btm.cs
318 | *.odx.cs
319 | *.xsd.cs
320 |
321 | # OpenCover UI analysis results
322 | OpenCover/
323 |
324 | # Azure Stream Analytics local run output
325 | ASALocalRun/
326 |
327 | # MSBuild Binary and Structured Log
328 | *.binlog
329 |
330 | # NVidia Nsight GPU debugger configuration file
331 | *.nvuser
332 |
333 | # MFractors (Xamarin productivity tool) working folder
334 | .mfractor/
335 |
336 | # Local History for Visual Studio
337 | .localhistory/
338 |
339 | # BeatPulse healthcheck temp database
340 | healthchecksdb
--------------------------------------------------------------------------------
/PixivFSUWP.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.28803.156
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PixivFSUWP", "PixivFSUWP\PixivFSUWP.csproj", "{F865197F-54E9-482F-B559-D577D81D4A46}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|ARM = Debug|ARM
11 | Debug|ARM64 = Debug|ARM64
12 | Debug|x64 = Debug|x64
13 | Debug|x86 = Debug|x86
14 | Release|ARM = Release|ARM
15 | Release|ARM64 = Release|ARM64
16 | Release|x64 = Release|x64
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {F865197F-54E9-482F-B559-D577D81D4A46}.Debug|ARM.ActiveCfg = Debug|ARM
21 | {F865197F-54E9-482F-B559-D577D81D4A46}.Debug|ARM.Build.0 = Debug|ARM
22 | {F865197F-54E9-482F-B559-D577D81D4A46}.Debug|ARM.Deploy.0 = Debug|ARM
23 | {F865197F-54E9-482F-B559-D577D81D4A46}.Debug|ARM64.ActiveCfg = Debug|ARM64
24 | {F865197F-54E9-482F-B559-D577D81D4A46}.Debug|ARM64.Build.0 = Debug|ARM64
25 | {F865197F-54E9-482F-B559-D577D81D4A46}.Debug|ARM64.Deploy.0 = Debug|ARM64
26 | {F865197F-54E9-482F-B559-D577D81D4A46}.Debug|x64.ActiveCfg = Debug|x64
27 | {F865197F-54E9-482F-B559-D577D81D4A46}.Debug|x64.Build.0 = Debug|x64
28 | {F865197F-54E9-482F-B559-D577D81D4A46}.Debug|x64.Deploy.0 = Debug|x64
29 | {F865197F-54E9-482F-B559-D577D81D4A46}.Debug|x86.ActiveCfg = Debug|x86
30 | {F865197F-54E9-482F-B559-D577D81D4A46}.Debug|x86.Build.0 = Debug|x86
31 | {F865197F-54E9-482F-B559-D577D81D4A46}.Debug|x86.Deploy.0 = Debug|x86
32 | {F865197F-54E9-482F-B559-D577D81D4A46}.Release|ARM.ActiveCfg = Release|ARM
33 | {F865197F-54E9-482F-B559-D577D81D4A46}.Release|ARM.Build.0 = Release|ARM
34 | {F865197F-54E9-482F-B559-D577D81D4A46}.Release|ARM.Deploy.0 = Release|ARM
35 | {F865197F-54E9-482F-B559-D577D81D4A46}.Release|ARM64.ActiveCfg = Release|ARM64
36 | {F865197F-54E9-482F-B559-D577D81D4A46}.Release|ARM64.Build.0 = Release|ARM64
37 | {F865197F-54E9-482F-B559-D577D81D4A46}.Release|ARM64.Deploy.0 = Release|ARM64
38 | {F865197F-54E9-482F-B559-D577D81D4A46}.Release|x64.ActiveCfg = Release|x64
39 | {F865197F-54E9-482F-B559-D577D81D4A46}.Release|x64.Build.0 = Release|x64
40 | {F865197F-54E9-482F-B559-D577D81D4A46}.Release|x64.Deploy.0 = Release|x64
41 | {F865197F-54E9-482F-B559-D577D81D4A46}.Release|x86.ActiveCfg = Release|x86
42 | {F865197F-54E9-482F-B559-D577D81D4A46}.Release|x86.Build.0 = Release|x86
43 | {F865197F-54E9-482F-B559-D577D81D4A46}.Release|x86.Deploy.0 = Release|x86
44 | EndGlobalSection
45 | GlobalSection(SolutionProperties) = preSolution
46 | HideSolutionNode = FALSE
47 | EndGlobalSection
48 | GlobalSection(ExtensibilityGlobals) = postSolution
49 | SolutionGuid = {BB0AC073-DB55-4D1B-91CA-39929BA2B0EE}
50 | EndGlobalSection
51 | EndGlobal
52 |
--------------------------------------------------------------------------------
/PixivFSUWP/App.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
51 |
52 |
53 |
54 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
136 |
137 |
138 |
139 |
--------------------------------------------------------------------------------
/PixivFSUWP/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.ApplicationModel;
7 | using Windows.ApplicationModel.Activation;
8 | using Windows.Foundation;
9 | using Windows.Foundation.Collections;
10 | using Windows.UI.Popups;
11 | using Windows.UI.Xaml;
12 | using Windows.UI.Xaml.Controls;
13 | using Windows.UI.Xaml.Controls.Primitives;
14 | using Windows.UI.Xaml.Data;
15 | using Windows.UI.Xaml.Input;
16 | using Windows.UI.Xaml.Media;
17 | using Windows.UI.Xaml.Media.Animation;
18 | using Windows.UI.Xaml.Navigation;
19 |
20 | namespace PixivFSUWP
21 | {
22 | ///
23 | /// 提供特定于应用程序的行为,以补充默认的应用程序类。
24 | ///
25 | sealed partial class App : Application
26 | {
27 | Windows.Storage.ApplicationDataContainer localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
28 | // 什么叫流畅设计啊(后仰
29 | public static NavigationTransitionInfo FromRightTransitionInfo = new SlideNavigationTransitionInfo() { Effect = SlideNavigationTransitionEffect.FromRight };
30 | public static NavigationTransitionInfo FromLeftTransitionInfo = new SlideNavigationTransitionInfo() { Effect = SlideNavigationTransitionEffect.FromLeft };
31 | public static NavigationTransitionInfo DrillInTransitionInfo = new DrillInNavigationTransitionInfo();
32 |
33 | ///
34 | /// 初始化单一实例应用程序对象。这是执行的创作代码的第一行,
35 | /// 已执行,逻辑上等同于 main() 或 WinMain()。
36 | ///
37 | public App()
38 | {
39 | this.InitializeComponent();
40 | this.Suspending += OnSuspending;
41 | this.UnhandledException += App_UnhandledException;
42 | switch (localSettings.Values["ColorTheme"])
43 | {
44 | case false:
45 | Current.RequestedTheme = ApplicationTheme.Light;
46 | break;
47 | case true:
48 | Current.RequestedTheme = ApplicationTheme.Dark;
49 | break;
50 | }
51 | }
52 |
53 | private void App_UnhandledException(object sender, Windows.UI.Xaml.UnhandledExceptionEventArgs e)
54 | {
55 | //遇到未处理的异常时
56 | e.Handled = true;
57 | if (localSettings.Values.ContainsKey("exception"))
58 | localSettings.Values.Remove("exception");
59 | localSettings.Values["exception"] = e.Exception.ToString();
60 | localSettings.Values["isCrashed"] = true;
61 | //只储存异常信息,而不强制退出应用。很多异常不影响应用稳定性。
62 | //MessageDialog dialog = new MessageDialog("Pixiv UWP has crashed. Please restart this app in order to report this issue.\n程序已崩溃,请重启本应用以便于报告此问题。", "Crashed/程序崩溃");
63 | //await dialog.ShowAsync();
64 | //this.Exit();
65 | }
66 |
67 | protected override void OnActivated(IActivatedEventArgs args)
68 | {
69 | //由Uri启动时
70 | if (args.Kind == ActivationKind.Protocol)
71 | {
72 | ProtocolActivatedEventArgs eventArgs = args as ProtocolActivatedEventArgs;
73 |
74 | //储存Uri
75 | Data.OverAll.AppUri = eventArgs.Uri;
76 |
77 | //按照正常流程启动应用
78 | Frame rootFrame = Window.Current.Content as Frame;
79 | if (rootFrame == null)
80 | {
81 | rootFrame = new Frame();
82 | rootFrame.NavigationFailed += OnNavigationFailed;
83 | if (eventArgs.PreviousExecutionState == ApplicationExecutionState.Terminated)
84 | {
85 | //TODO: 从之前挂起的应用程序加载状态
86 | }
87 | Window.Current.Content = rootFrame;
88 | }
89 | if (rootFrame.Content == null)
90 | {
91 | rootFrame.Navigate(typeof(LoginPage));
92 | }
93 | else if (rootFrame.Content is MainPage)
94 | {
95 | (rootFrame.Content as MainPage).HandleUri();
96 | }
97 | Window.Current.Activate();
98 | }
99 | }
100 |
101 | ///
102 | /// 在应用程序由最终用户正常启动时进行调用。
103 | /// 将在启动应用程序以打开特定文件等情况下使用。
104 | ///
105 | /// 有关启动请求和过程的详细信息。
106 | protected override void OnLaunched(LaunchActivatedEventArgs e)
107 | {
108 | Frame rootFrame = Window.Current.Content as Frame;
109 |
110 | // 不要在窗口已包含内容时重复应用程序初始化,
111 | // 只需确保窗口处于活动状态
112 | if (rootFrame == null)
113 | {
114 | // 创建要充当导航上下文的框架,并导航到第一页
115 | rootFrame = new Frame();
116 |
117 | rootFrame.NavigationFailed += OnNavigationFailed;
118 |
119 | if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
120 | {
121 | //TODO: 从之前挂起的应用程序加载状态
122 | }
123 |
124 | // 将框架放在当前窗口中
125 | Window.Current.Content = rootFrame;
126 | }
127 |
128 | if (e.PrelaunchActivated == false)
129 | {
130 | if (rootFrame.Content == null)
131 | {
132 | ////检测上次的崩溃
133 | //if (localSettings.Values["isCrashed"] != null && (bool)localSettings.Values["isCrashed"] == true)
134 | //{
135 | // localSettings.Values.Remove("isCrashed");
136 | // var yesCommand = new UICommand("Yes/是");
137 | // var noCommand = new UICommand("No/否");
138 | // MessageDialog dialog = new MessageDialog("A crash has been detected in your last session. Do you want to report this issue?\n在您上次的会话中我们探测到一次崩溃。请问您要报告此问题吗?", "Crash Report/错误报告");
139 | // dialog.Commands.Add(yesCommand);
140 | // dialog.Commands.Add(noCommand);
141 | // dialog.DefaultCommandIndex = 0;
142 | // var cmd = await dialog.ShowAsync();
143 | // if (cmd == yesCommand)
144 | // {
145 | // rootFrame.Navigate(typeof(ReportIssuePage), e.Arguments);
146 | // }
147 | // else
148 | // {
149 | // rootFrame.Navigate(typeof(LoginPage), e.Arguments);
150 | // }
151 | //}
152 | //else
153 | //不再在程序起始时弹出反馈窗口
154 | rootFrame.Navigate(typeof(LoginPage), e.Arguments, App.FromRightTransitionInfo);
155 | }
156 | // 确保当前窗口处于活动状态
157 | Window.Current.Activate();
158 | }
159 | }
160 |
161 | ///
162 | /// 导航到特定页失败时调用
163 | ///
164 | ///导航失败的框架
165 | ///有关导航失败的详细信息
166 | void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
167 | {
168 | throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
169 | }
170 |
171 | ///
172 | /// 在将要挂起应用程序执行时调用。 在不知道应用程序
173 | /// 无需知道应用程序会被终止还是会恢复,
174 | /// 并让内存内容保持不变。
175 | ///
176 | /// 挂起的请求的源。
177 | /// 有关挂起请求的详细信息。
178 | private void OnSuspending(object sender, SuspendingEventArgs e)
179 | {
180 | var deferral = e.SuspendingOperation.GetDeferral();
181 | //TODO: 保存应用程序状态并停止任何后台活动
182 | deferral.Complete();
183 | }
184 | }
185 | }
186 |
--------------------------------------------------------------------------------
/PixivFSUWP/Assets/AppLogo.kra:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sovetskyfish/pixivfs-uwp/c3e1b8d8cd4eb0f1762c586622d2b21c5103a45e/PixivFSUWP/Assets/AppLogo.kra
--------------------------------------------------------------------------------
/PixivFSUWP/Assets/GH_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sovetskyfish/pixivfs-uwp/c3e1b8d8cd4eb0f1762c586622d2b21c5103a45e/PixivFSUWP/Assets/GH_64.png
--------------------------------------------------------------------------------
/PixivFSUWP/Assets/LockScreenLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sovetskyfish/pixivfs-uwp/c3e1b8d8cd4eb0f1762c586622d2b21c5103a45e/PixivFSUWP/Assets/LockScreenLogo.scale-200.png
--------------------------------------------------------------------------------
/PixivFSUWP/Assets/LoginBG.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sovetskyfish/pixivfs-uwp/c3e1b8d8cd4eb0f1762c586622d2b21c5103a45e/PixivFSUWP/Assets/LoginBG.jpg
--------------------------------------------------------------------------------
/PixivFSUWP/Assets/PixivHeader.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sovetskyfish/pixivfs-uwp/c3e1b8d8cd4eb0f1762c586622d2b21c5103a45e/PixivFSUWP/Assets/PixivHeader.png
--------------------------------------------------------------------------------
/PixivFSUWP/Assets/PixivHeader_L.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sovetskyfish/pixivfs-uwp/c3e1b8d8cd4eb0f1762c586622d2b21c5103a45e/PixivFSUWP/Assets/PixivHeader_L.png
--------------------------------------------------------------------------------
/PixivFSUWP/Assets/PixivText.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sovetskyfish/pixivfs-uwp/c3e1b8d8cd4eb0f1762c586622d2b21c5103a45e/PixivFSUWP/Assets/PixivText.png
--------------------------------------------------------------------------------
/PixivFSUWP/Assets/PixivText_L.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sovetskyfish/pixivfs-uwp/c3e1b8d8cd4eb0f1762c586622d2b21c5103a45e/PixivFSUWP/Assets/PixivText_L.png
--------------------------------------------------------------------------------
/PixivFSUWP/Assets/Pixiv_Logo.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/PixivFSUWP/Assets/QQ_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sovetskyfish/pixivfs-uwp/c3e1b8d8cd4eb0f1762c586622d2b21c5103a45e/PixivFSUWP/Assets/QQ_64.png
--------------------------------------------------------------------------------
/PixivFSUWP/Assets/SauceNAO.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sovetskyfish/pixivfs-uwp/c3e1b8d8cd4eb0f1762c586622d2b21c5103a45e/PixivFSUWP/Assets/SauceNAO.png
--------------------------------------------------------------------------------
/PixivFSUWP/Assets/SplashScreen.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sovetskyfish/pixivfs-uwp/c3e1b8d8cd4eb0f1762c586622d2b21c5103a45e/PixivFSUWP/Assets/SplashScreen.scale-200.png
--------------------------------------------------------------------------------
/PixivFSUWP/Assets/Square150x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sovetskyfish/pixivfs-uwp/c3e1b8d8cd4eb0f1762c586622d2b21c5103a45e/PixivFSUWP/Assets/Square150x150Logo.scale-200.png
--------------------------------------------------------------------------------
/PixivFSUWP/Assets/Square44x44Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sovetskyfish/pixivfs-uwp/c3e1b8d8cd4eb0f1762c586622d2b21c5103a45e/PixivFSUWP/Assets/Square44x44Logo.scale-200.png
--------------------------------------------------------------------------------
/PixivFSUWP/Assets/Square44x44Logo.targetsize-256_altform-unplated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sovetskyfish/pixivfs-uwp/c3e1b8d8cd4eb0f1762c586622d2b21c5103a45e/PixivFSUWP/Assets/Square44x44Logo.targetsize-256_altform-unplated.png
--------------------------------------------------------------------------------
/PixivFSUWP/Assets/Square71x71Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sovetskyfish/pixivfs-uwp/c3e1b8d8cd4eb0f1762c586622d2b21c5103a45e/PixivFSUWP/Assets/Square71x71Logo.scale-200.png
--------------------------------------------------------------------------------
/PixivFSUWP/Assets/StoreLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sovetskyfish/pixivfs-uwp/c3e1b8d8cd4eb0f1762c586622d2b21c5103a45e/PixivFSUWP/Assets/StoreLogo.png
--------------------------------------------------------------------------------
/PixivFSUWP/BigImage.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
14 |
15 |
16 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/PixivFSUWP/Controls/ImageSelectorPanel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.Foundation;
7 | using Windows.UI.Xaml;
8 | using Windows.UI.Xaml.Controls;
9 |
10 | namespace PixivFSUWP.Controls
11 | {
12 | public class ImageSelectorPanel : Panel
13 | {
14 | //此属性决定项目间隔
15 | public static readonly DependencyProperty ItemMarginProperty =
16 | DependencyProperty.Register("ItemMargin", typeof(double),
17 | typeof(ImageSelectorPanel), new PropertyMetadata((double)0,
18 | (DepObj, e) =>
19 | {
20 | (DepObj as ImageSelectorPanel).InvalidateMeasure();
21 | (DepObj as ImageSelectorPanel).InvalidateArrange();
22 | }));
23 |
24 | public double ItemMargin
25 | {
26 | get => (double)GetValue(ItemMarginProperty);
27 | set => SetValue(ItemMarginProperty, value);
28 | }
29 |
30 | //此属性决定左端间距
31 | public static readonly DependencyProperty LeftOffsetProperty =
32 | DependencyProperty.Register("LeftOffset", typeof(double),
33 | typeof(ImageSelectorPanel), new PropertyMetadata((double)0,
34 | (DepObj, e) =>
35 | {
36 | (DepObj as ImageSelectorPanel).InvalidateMeasure();
37 | (DepObj as ImageSelectorPanel).InvalidateArrange();
38 | }));
39 |
40 | public double LeftOffset
41 | {
42 | get => (double)GetValue(LeftOffsetProperty);
43 | set => SetValue(LeftOffsetProperty, value);
44 | }
45 |
46 | //此属性决定右端间距
47 | public static readonly DependencyProperty RightOffsetProperty =
48 | DependencyProperty.Register("RightOffset", typeof(double),
49 | typeof(ImageSelectorPanel), new PropertyMetadata((double)0,
50 | (DepObj, e) =>
51 | {
52 | (DepObj as ImageSelectorPanel).InvalidateMeasure();
53 | (DepObj as ImageSelectorPanel).InvalidateArrange();
54 | }));
55 |
56 | public double RightOffset
57 | {
58 | get => (double)GetValue(RightOffsetProperty);
59 | set => SetValue(RightOffsetProperty, value);
60 | }
61 |
62 | protected override Size MeasureOverride(Size availableSize)
63 | {
64 | Size toret = new Size();
65 | toret.Height = availableSize.Height;
66 | toret.Width = LeftOffset + ItemMargin * (Children.Count - 1) + RightOffset;
67 | foreach (var i in Children)
68 | {
69 | i.Measure(new Size(double.PositiveInfinity, toret.Height));
70 | toret.Width += i.DesiredSize.Width;
71 | }
72 | return toret;
73 | }
74 |
75 | protected override Size ArrangeOverride(Size finalSize)
76 | {
77 | double xOffset = LeftOffset;
78 | foreach (var i in Children)
79 | {
80 | i.Arrange(new Rect(xOffset, 0, i.DesiredSize.Width, i.DesiredSize.Height));
81 | xOffset += i.DesiredSize.Width + ItemMargin;
82 | }
83 | return finalSize;
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/PixivFSUWP/Controls/Pixiv_Logo.xaml:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/PixivFSUWP/Controls/Pixiv_Logo.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 |
16 | //https://go.microsoft.com/fwlink/?LinkId=234236 上介绍了“用户控件”项模板
17 |
18 | namespace PixivFSUWP.Controls
19 | {
20 | public sealed partial class Pixiv_Logo
21 | {
22 | public Pixiv_Logo()
23 | {
24 | this.InitializeComponent();
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/PixivFSUWP/Controls/TagsPanel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.Foundation;
7 | using Windows.UI.Xaml;
8 | using Windows.UI.Xaml.Controls;
9 |
10 | namespace PixivFSUWP.Controls
11 | {
12 | public class TagsPanel : Panel
13 | {
14 | //行距
15 | public static readonly DependencyProperty ItemVerticalMarginProperty =
16 | DependencyProperty.Register("ItemVerticalMargin", typeof(double),
17 | typeof(TagsPanel), new PropertyMetadata((double)0,
18 | (DepObj, e) =>
19 | {
20 | (DepObj as TagsPanel).InvalidateMeasure();
21 | (DepObj as TagsPanel).InvalidateArrange();
22 | }));
23 |
24 | public double ItemVerticalMargin
25 | {
26 | get => (double)GetValue(ItemVerticalMarginProperty);
27 | set => SetValue(ItemVerticalMarginProperty, value);
28 | }
29 |
30 | //项目水平间隔
31 | public static readonly DependencyProperty ItemHorizontalMarginProperty =
32 | DependencyProperty.Register("ItemHorizontalMargin", typeof(double),
33 | typeof(TagsPanel), new PropertyMetadata((double)0,
34 | (DepObj, e) =>
35 | {
36 | (DepObj as TagsPanel).InvalidateMeasure();
37 | (DepObj as TagsPanel).InvalidateArrange();
38 | }));
39 |
40 | public double ItemHorizontalMargin
41 | {
42 | get => (double)GetValue(ItemHorizontalMarginProperty);
43 | set => SetValue(ItemHorizontalMarginProperty, value);
44 | }
45 |
46 | //行高
47 | public static readonly DependencyProperty ItemHeightProperty =
48 | DependencyProperty.Register("ItemHeight", typeof(double),
49 | typeof(TagsPanel), new PropertyMetadata((double)20,
50 | (DepObj, e) =>
51 | {
52 | (DepObj as TagsPanel).InvalidateMeasure();
53 | (DepObj as TagsPanel).InvalidateArrange();
54 | }));
55 |
56 | public double ItemHeight
57 | {
58 | get => (double)GetValue(ItemHeightProperty);
59 | set => SetValue(ItemHeightProperty, value);
60 | }
61 |
62 | protected override Size MeasureOverride(Size availableSize)
63 | {
64 | if (Children.Count == 0) return new Size(0, 0);
65 | List widths = new List();
66 | widths.Add(-ItemHorizontalMargin);
67 | int rowCount = 1;
68 | foreach (var child in Children)
69 | {
70 | child.Measure(new Size(availableSize.Width, ItemHeight));
71 | double tmpWidth = widths[rowCount - 1] + ItemHorizontalMargin + child.DesiredSize.Width;
72 | if (tmpWidth > availableSize.Width)
73 | {
74 | rowCount++;
75 | widths.Add(child.DesiredSize.Width);
76 | }
77 | else
78 | widths[rowCount - 1] = tmpWidth;
79 | }
80 | return new Size(widths.Max(), rowCount * ItemHeight + (rowCount - 1) * ItemVerticalMargin);
81 | }
82 |
83 | protected override Size ArrangeOverride(Size finalSize)
84 | {
85 | List widths = new List();
86 | widths.Add(-ItemHorizontalMargin);
87 | int rowCount = 1;
88 | foreach (var child in Children)
89 | {
90 | double tmpWidth = widths[rowCount - 1] + ItemHorizontalMargin + child.DesiredSize.Width;
91 | if (tmpWidth > finalSize.Width)
92 | {
93 | rowCount++;
94 | widths.Add(child.DesiredSize.Width);
95 | child.Arrange(new Rect(0, (rowCount - 1) * (ItemHeight + ItemVerticalMargin),
96 | child.DesiredSize.Width, child.DesiredSize.Height));
97 | }
98 | else
99 | {
100 | child.Arrange(new Rect(widths[rowCount - 1] + ItemHorizontalMargin,
101 | (rowCount - 1) * (ItemHeight + ItemVerticalMargin),
102 | child.DesiredSize.Width, child.DesiredSize.Height));
103 | widths[rowCount - 1] = tmpWidth;
104 | }
105 | }
106 | return finalSize;
107 | }
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/PixivFSUWP/Controls/WaterfallContentPanel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.Foundation;
7 | using Windows.UI.Xaml;
8 | using Windows.UI.Xaml.Controls;
9 |
10 | namespace PixivFSUWP.Controls
11 | {
12 | public class WaterfallContentPanel : Panel
13 | {
14 | //此属性决定瀑布流列数
15 | public static readonly DependencyProperty ColumsProperty =
16 | DependencyProperty.Register("Colums", typeof(int),
17 | typeof(WaterfallContentPanel), new PropertyMetadata(2,
18 | (DepObj, e) =>
19 | {
20 | (DepObj as WaterfallContentPanel).InvalidateMeasure();
21 | (DepObj as WaterfallContentPanel).InvalidateArrange();
22 | }));
23 |
24 | public int Colums
25 | {
26 | get => (int)GetValue(ColumsProperty);
27 | set => SetValue(ColumsProperty, value);
28 | }
29 |
30 | //此属性决定项目间隔
31 | public static readonly DependencyProperty ItemMarginProperty =
32 | DependencyProperty.Register("ItemMargin", typeof(double),
33 | typeof(WaterfallContentPanel), new PropertyMetadata((double)0,
34 | (DepObj, e) =>
35 | {
36 | (DepObj as WaterfallContentPanel).InvalidateMeasure();
37 | (DepObj as WaterfallContentPanel).InvalidateArrange();
38 | }));
39 |
40 | public double ItemMargin
41 | {
42 | get => (double)GetValue(ItemMarginProperty);
43 | set => SetValue(ItemMarginProperty, value);
44 | }
45 |
46 | //此属性决定顶端间距
47 | public static readonly DependencyProperty TopOffsetProperty =
48 | DependencyProperty.Register("TopOffset", typeof(double),
49 | typeof(WaterfallContentPanel), new PropertyMetadata((double)0,
50 | (DepObj, e) =>
51 | {
52 | (DepObj as WaterfallContentPanel).InvalidateMeasure();
53 | (DepObj as WaterfallContentPanel).InvalidateArrange();
54 | }));
55 |
56 | public double TopOffset
57 | {
58 | get => (double)GetValue(TopOffsetProperty);
59 | set => SetValue(TopOffsetProperty, value);
60 | }
61 |
62 | //测量panel需要的空间
63 | //宽度填满,高度进行计算
64 | protected override Size MeasureOverride(Size availableSize)
65 | {
66 | Size toret = new Size();
67 | List heights = (new double[Colums]).ToList();
68 | toret.Width = availableSize.Width;
69 | double itemwidth = (availableSize.Width - ItemMargin * (Colums - 1)) / Colums;
70 | foreach (var i in Children)
71 | {
72 | i.Measure(new Size(itemwidth, double.PositiveInfinity));
73 | heights[heights.IndexOf(heights.Min())] += ItemMargin + i.DesiredSize.Height;
74 | }
75 | toret.Height = heights.Max() + TopOffset;
76 | return toret;
77 | }
78 |
79 | //排版,不改变大小
80 | protected override Size ArrangeOverride(Size finalSize)
81 | {
82 | List Xs = new List();
83 | List Ys = new List();
84 | for (int i = 0; i < Colums; i++)
85 | {
86 | Xs.Add(i * (DesiredSize.Width + ItemMargin) / Colums);
87 | Ys.Add(TopOffset);
88 | }
89 | foreach (var i in Children)
90 | {
91 | var minC = Ys.IndexOf(Ys.Min());
92 | i.Arrange(new Rect(Xs[minC], Ys[minC], i.DesiredSize.Width, i.DesiredSize.Height));
93 | Ys[minC] += i.DesiredSize.Height + ItemMargin;
94 | }
95 | return finalSize;
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/PixivFSUWP/Controls/WaterfallListView.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.Foundation;
7 | using Windows.UI.Xaml;
8 | using Windows.UI.Xaml.Controls;
9 | using Windows.UI.Xaml.Data;
10 |
11 | namespace PixivFSUWP.Controls
12 | {
13 | //似乎是我的panel弄坏了ListView,这里只能自己造一个(lll¬ω¬)
14 | public class WaterfallListView : ListView
15 | {
16 | bool busyLoading = false;
17 |
18 | public WaterfallListView() : base()
19 | {
20 | //不使用base的增量加载
21 | IncrementalLoadingTrigger = IncrementalLoadingTrigger.None;
22 | }
23 |
24 | protected override void OnApplyTemplate()
25 | {
26 | base.OnApplyTemplate();
27 | var scrollViewer = GetTemplateChild("ScrollViewer") as ScrollViewer;
28 | scrollViewer.ViewChanged += ScrollViewer_ViewChanged;
29 | _ = LoadPage();
30 | }
31 |
32 | private async Task LoadPage()
33 | {
34 | var scrollViewer = GetTemplateChild("ScrollViewer") as ScrollViewer;
35 | busyLoading = true;
36 | try
37 | {
38 | while (scrollViewer.ScrollableHeight == 0)
39 | try
40 | {
41 | var res = await (ItemsSource as ISupportIncrementalLoading)?.LoadMoreItemsAsync(0);
42 | if (res.Count == 0) return;
43 | }
44 | catch (InvalidOperationException)
45 | {
46 | return;
47 | }
48 | }
49 | finally
50 | {
51 | busyLoading = false;
52 | }
53 | }
54 |
55 | private async void ScrollViewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
56 | {
57 | if (busyLoading) return;
58 | busyLoading = true;
59 | try
60 | {
61 | while ((sender as ScrollViewer).VerticalOffset >= (sender as ScrollViewer).ScrollableHeight - 500)
62 | {
63 | try
64 | {
65 | var res = await (ItemsSource as ISupportIncrementalLoading)?.LoadMoreItemsAsync(0);
66 | if (res.Count == 0) return;
67 | }
68 | catch (InvalidOperationException)
69 | {
70 | return;
71 | }
72 | catch { }
73 | }
74 | }
75 | finally
76 | {
77 | busyLoading = false;
78 | }
79 | }
80 |
81 | public void ScrollToItem(UIElement element)
82 | {
83 | var transform = TransformToVisual(element);
84 | Point absolutePosition = transform.TransformPoint(new Point(0, 0));
85 | var scrollViewer = GetTemplateChild("ScrollViewer") as ScrollViewer;
86 | scrollViewer.ChangeView(null, -absolutePosition.Y - 75, null, true);
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/PixivFSUWP/Converters/BookmarkHeartVisibilityConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.UI.Xaml;
7 | using Windows.UI.Xaml.Data;
8 |
9 | namespace PixivFSUWP.Converters
10 | {
11 | public class BookmarkHeartVisibilityConverter : IValueConverter
12 | {
13 | public object Convert(object value, Type targetType, object parameter, string language)
14 | {
15 | bool isBookmarked = (bool)value;
16 | return isBookmarked ? Visibility.Visible : Visibility.Collapsed;
17 | }
18 |
19 | public object ConvertBack(object value, Type targetType, object parameter, string language)
20 | {
21 | throw new NotImplementedException();
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/PixivFSUWP/Converters/ChildrenCommentVisibilityConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Windows.UI.Xaml;
8 | using Windows.UI.Xaml.Data;
9 |
10 | namespace PixivFSUWP.Converters
11 | {
12 | public class ChildrenCommentVisibilityConverter : IValueConverter
13 | {
14 | public object Convert(object value, Type targetType, object parameter, string language)
15 | {
16 | var childrenComments = value as ObservableCollection;
17 | if (childrenComments == null) return Visibility.Collapsed;
18 | if (childrenComments.Count == 0) return Visibility.Collapsed;
19 | return Visibility.Visible;
20 | }
21 |
22 | public object ConvertBack(object value, Type targetType, object parameter, string language)
23 | {
24 | throw new NotImplementedException();
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/PixivFSUWP/Converters/ContributionsConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.UI.Xaml.Data;
7 |
8 | namespace PixivFSUWP.Converters
9 | {
10 | public class ContributionsConverter : IValueConverter
11 | {
12 | public object Convert(object value, Type targetType, object parameter, string language)
13 | {
14 | string toret = "";
15 | if (value == null) return toret;
16 | var source = value as List;
17 | source.Sort();
18 | foreach (var contribution in source)
19 | {
20 | switch (contribution)
21 | {
22 | case Data.Contribution.bug:
23 | toret += "🐛";
24 | break;
25 | case Data.Contribution.code:
26 | toret += "💻";
27 | break;
28 | case Data.Contribution.doc:
29 | toret += "📖";
30 | break;
31 | case Data.Contribution.idea:
32 | toret += "🤔";
33 | break;
34 | case Data.Contribution.translation:
35 | toret += "🌍";
36 | break;
37 | case Data.Contribution.unknown:
38 | toret += "❓";
39 | break;
40 | }
41 | }
42 | return toret;
43 | }
44 |
45 | public object ConvertBack(object value, Type targetType, object parameter, string language)
46 | {
47 | throw new NotImplementedException();
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/PixivFSUWP/Converters/MultiPageVisibilityConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.UI.Xaml;
7 | using Windows.UI.Xaml.Data;
8 |
9 | namespace PixivFSUWP.Converters
10 | {
11 | public class MultiPageVisibilityConverter : IValueConverter
12 | {
13 | public object Convert(object value, Type targetType, object parameter, string language)
14 | {
15 | int pageCount = (int)value;
16 | if (pageCount > 1) return Visibility.Visible;
17 | else return Visibility.Collapsed;
18 | }
19 |
20 | public object ConvertBack(object value, Type targetType, object parameter, string language)
21 | {
22 | throw new NotImplementedException();
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/PixivFSUWP/Data/Backstack.cs:
--------------------------------------------------------------------------------
1 | using PixivFSUWP.Interfaces;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Windows.UI.Xaml.Controls;
8 |
9 | namespace PixivFSUWP.Data
10 | {
11 | public class Backstack : Stack<(Type, object)>
12 | {
13 | public static Backstack Default { get; } = new Backstack();
14 |
15 | public bool CanBack
16 | {
17 | get => base.Count > 0;
18 | }
19 |
20 | public void Push(Type Page, object Parameter)
21 | {
22 | base.Push((Page, Parameter));
23 | }
24 |
25 | public object Back(Frame Frame)
26 | {
27 | if (!CanBack) throw new InvalidOperationException();
28 | (var page, var param) = base.Pop();
29 | Frame.Navigate(page, param, App.FromLeftTransitionInfo);
30 | return param;
31 | }
32 | }
33 |
34 | public static class FrameBackstackExtended
35 | {
36 | public static object Back(this Frame source)
37 | {
38 | (source.Content as IGoBackFlag).SetBackFlag(true);
39 | return Backstack.Default.Back(source);
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/PixivFSUWP/Data/BigImageDetail.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.Storage;
7 | using Windows.UI.Xaml.Media.Imaging;
8 |
9 | namespace PixivFSUWP.Data
10 | {
11 | public class BigImageDetail
12 | {
13 | public string Title { get; set; }
14 | public string Author { get; set; }
15 | public int Width { get; set; }
16 | public int Height { get; set; }
17 | public byte[] Image { get; set; }
18 | public string FileName { get; set; }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/PixivFSUWP/Data/CacheManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.Storage;
7 |
8 | namespace PixivFSUWP.Data
9 | {
10 | //记录临时的缓存文件及其期望的名称
11 | public struct TempStorageFile
12 | {
13 | public StorageFile File;
14 | public string ExpectedName;
15 | }
16 |
17 | //用来管理缓存
18 | public static class CacheManager
19 | {
20 | //临时目录
21 | private static StorageFolder tmpFolder = ApplicationData.Current.TemporaryFolder;
22 |
23 | //获取临时目录,确保目录存在
24 | private static async Task getCacheFolderAsync()
25 | {
26 | var cacheFolder = await tmpFolder.TryGetItemAsync("Cache");
27 | if (cacheFolder == null) return await tmpFolder.CreateFolderAsync("Cache");
28 | else return cacheFolder as StorageFolder;
29 | }
30 |
31 | //清除缓存
32 | public static async Task ClearCacheAsync()
33 | {
34 | var cacheFolder = await getCacheFolderAsync();
35 | await cacheFolder.DeleteAsync(StorageDeleteOption.PermanentDelete);
36 | }
37 |
38 | //得到目录大小
39 | private static async Task getFolderSizeAsync(StorageFolder target)
40 | {
41 | var getFileSizeTasks = from file
42 | in await target.CreateFileQuery().GetFilesAsync()
43 | select file.GetBasicPropertiesAsync().AsTask();
44 | var fileSizes = await Task.WhenAll(getFileSizeTasks);
45 | return fileSizes.Sum(i => (long)i.Size);
46 | }
47 |
48 | //得到缓存目录大小
49 | public static async Task GetCacheSizeAsync()
50 | => await getFolderSizeAsync(await getCacheFolderAsync());
51 |
52 | //得到缓存文件
53 | public static async Task GetCachedFileAsync(string Filename)
54 | {
55 | var cacheFolder = await getCacheFolderAsync();
56 | if (await cacheFolder.TryGetItemAsync(Filename) == null) return null;
57 | return await cacheFolder.GetFileAsync(Filename);
58 | }
59 |
60 | //删除缓存文件
61 | public static async Task DeleteCachedFileAsync(string Filename)
62 | {
63 | var file = await GetCachedFileAsync(Filename);
64 | if (file == null) return false;
65 | await file.DeleteAsync(StorageDeleteOption.PermanentDelete);
66 | return true;
67 | }
68 |
69 | //创建缓存文件
70 | //文件将以随机的Guid命名,完成写入时再命名为期望的文件名
71 | //此举有助于防止写入一半时程序非法终止而产生损坏的缓存文件
72 | public static async Task CreateCacheFileAsync(string Filename)
73 | {
74 | Guid guid;
75 | var test = Guid.TryParse(Filename, out guid);
76 | //避免使用GUID作为文件名
77 | if (test) return null;
78 | do guid = Guid.NewGuid();
79 | while (await GetCachedFileAsync(guid.ToString()) != null);
80 | var cacheFolder = await getCacheFolderAsync();
81 | var newFile = await cacheFolder.CreateFileAsync(guid.ToString());
82 | TempStorageFile result = new TempStorageFile();
83 | result.ExpectedName = Filename;
84 | result.File = newFile;
85 | return result;
86 | }
87 |
88 | //完成写入缓存文件
89 | //ForceUpdate: 是否覆盖已有的文件
90 | public static async Task FinishCachedFileAsync(TempStorageFile File, bool ForceUpdate = false)
91 | {
92 | try
93 | {
94 | if (await GetCachedFileAsync(File.ExpectedName) != null)
95 | {
96 | if (ForceUpdate) await DeleteCachedFileAsync(File.ExpectedName);
97 | else return false;
98 | }
99 | await File.File.MoveAsync(await getCacheFolderAsync(), File.ExpectedName);
100 | return true;
101 | }
102 | catch
103 | {
104 | return false;
105 | }
106 | }
107 |
108 | //清理名称为GUID的临时文件
109 | public static async Task ClearTempFilesAsync()
110 | {
111 | var deleteTempFilesTasks = from file
112 | in await (await getCacheFolderAsync()).CreateFileQuery().GetFilesAsync()
113 | where Guid.TryParse(file.Name, out _)
114 | select file.DeleteAsync(StorageDeleteOption.PermanentDelete).AsTask();
115 | await Task.WhenAll(deleteTempFilesTasks);
116 | }
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/PixivFSUWP/Data/Collections/BookmarkIllustsCollection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using System.Text;
7 | using System.Threading;
8 | using System.Threading.Tasks;
9 | using Windows.Foundation;
10 | using Windows.UI.Xaml.Data;
11 | using System.Web;
12 | using Windows.Data.Json;
13 |
14 | namespace PixivFSUWP.Data.Collections
15 | {
16 | public class BookmarkIllustsCollection : ObservableCollection, ISupportIncrementalLoading
17 | {
18 | readonly string userID;
19 | string nexturl = "begin";
20 | bool _busy = false;
21 | bool _emergencyStop = false;
22 | EventWaitHandle pause = new ManualResetEvent(true);
23 |
24 | public BookmarkIllustsCollection(string UserID)
25 | {
26 | userID = UserID;
27 | }
28 |
29 | public BookmarkIllustsCollection() : this(OverAll.GlobalBaseAPI.UserID) { }
30 |
31 | public bool HasMoreItems
32 | {
33 | get => !string.IsNullOrEmpty(nexturl);
34 | }
35 |
36 | public IAsyncOperation LoadMoreItemsAsync(uint count)
37 | {
38 | if (_busy)
39 | throw new InvalidOperationException("Only one operation in flight at a time");
40 | _busy = true;
41 | return AsyncInfo.Run((c) => LoadMoreItemsAsync(c, count));
42 | }
43 |
44 | public void StopLoading()
45 | {
46 | _emergencyStop = true;
47 | if (_busy)
48 | {
49 | ResumeLoading();
50 | }
51 | else
52 | {
53 | Clear();
54 | GC.Collect();
55 | }
56 | }
57 |
58 | public void PauseLoading()
59 | {
60 | pause.Reset();
61 | }
62 |
63 | public void ResumeLoading()
64 | {
65 | pause.Set();
66 | }
67 |
68 | protected async Task LoadMoreItemsAsync(CancellationToken c, uint count)
69 | {
70 | try
71 | {
72 | if (!HasMoreItems) return new LoadMoreItemsResult() { Count = 0 };
73 | LoadMoreItemsResult toret = new LoadMoreItemsResult() { Count = 0 };
74 | PixivCS.Objects.UserIllusts bookmarkres = null;
75 | try
76 | {
77 | if (nexturl == "begin")
78 | bookmarkres = await new PixivCS
79 | .PixivAppAPI(OverAll.GlobalBaseAPI)
80 | .GetUserBookmarksIllustAsync(userID);
81 | else
82 | {
83 | Uri next = new Uri(nexturl);
84 | string getparam(string param) => HttpUtility.ParseQueryString(next.Query).Get(param);
85 | bookmarkres = await new PixivCS
86 | .PixivAppAPI(OverAll.GlobalBaseAPI)
87 | .GetUserBookmarksIllustAsync(userID, getparam("restrict"),
88 | getparam("filter"), getparam("max_bookmark_id"));
89 | }
90 | }
91 | catch
92 | {
93 | return toret;
94 | }
95 | nexturl = bookmarkres.NextUrl?.ToString() ?? "";
96 | foreach (var recillust in bookmarkres.Illusts)
97 | {
98 | await Task.Run(() => pause.WaitOne());
99 | if (_emergencyStop)
100 | {
101 | nexturl = "";
102 | Clear();
103 | return new LoadMoreItemsResult() { Count = 0 };
104 | }
105 | WaterfallItem recommendi = WaterfallItem.FromObject(recillust);
106 | var recommendmodel = ViewModels.WaterfallItemViewModel.FromItem(recommendi);
107 | await recommendmodel.LoadImageAsync();
108 | Add(recommendmodel);
109 | toret.Count++;
110 | }
111 | return toret;
112 | }
113 | finally
114 | {
115 | _busy = false;
116 | if (_emergencyStop)
117 | {
118 | nexturl = "";
119 | Clear();
120 | GC.Collect();
121 | }
122 | }
123 | }
124 | }
125 | }
126 |
127 |
--------------------------------------------------------------------------------
/PixivFSUWP/Data/Collections/CommentsCollection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using System.Text;
7 | using System.Threading;
8 | using System.Threading.Tasks;
9 | using System.Web;
10 | using Windows.Data.Json;
11 | using Windows.Foundation;
12 | using Windows.UI.Xaml.Data;
13 |
14 | namespace PixivFSUWP.Data.Collections
15 | {
16 | public class CommentsCollection : ObservableCollection, ISupportIncrementalLoading
17 | {
18 | string nexturl = "begin";
19 | bool _busy = false;
20 | bool _emergencyStop = false;
21 | EventWaitHandle pause = new ManualResetEvent(true);
22 | readonly string illustid;
23 | List ChildrenComments = new List();
24 | public CommentAvatarLoader AvatarLoader;
25 |
26 | public CommentsCollection(string IllustID)
27 | {
28 | illustid = IllustID;
29 | AvatarLoader = new CommentAvatarLoader(this);
30 | }
31 |
32 | public bool HasMoreItems
33 | {
34 | get => !string.IsNullOrEmpty(nexturl);
35 | }
36 |
37 | public IAsyncOperation LoadMoreItemsAsync(uint count)
38 | {
39 | if (_busy)
40 | throw new InvalidOperationException("Only one operation in flight at a time");
41 | _busy = true;
42 | return AsyncInfo.Run((c) => LoadMoreItemsAsync(c, count));
43 | }
44 |
45 | public void StopLoading()
46 | {
47 | _emergencyStop = true;
48 | if (_busy)
49 | {
50 | ResumeLoading();
51 | }
52 | else
53 | {
54 | Clear();
55 | GC.Collect();
56 | }
57 | }
58 |
59 | public void PauseLoading()
60 | {
61 | pause.Reset();
62 | }
63 |
64 | public void ResumeLoading()
65 | {
66 | pause.Set();
67 | }
68 |
69 | protected async Task LoadMoreItemsAsync(CancellationToken c, uint count)
70 | {
71 | try
72 | {
73 | if (!HasMoreItems) return new LoadMoreItemsResult() { Count = 0 };
74 | LoadMoreItemsResult toret = new LoadMoreItemsResult() { Count = 0 };
75 | PixivCS.Objects.IllustComments commentres = null;
76 | try
77 | {
78 | if (nexturl == "begin")
79 | commentres = await new PixivCS
80 | .PixivAppAPI(OverAll.GlobalBaseAPI)
81 | .GetIllustCommentsAsync(illustid, IncludeTotalComments: true);
82 | else
83 | {
84 | Uri next = new Uri(nexturl);
85 | string getparam(string param) => HttpUtility.ParseQueryString(next.Query).Get(param);
86 | commentres = await new PixivCS
87 | .PixivAppAPI(OverAll.GlobalBaseAPI)
88 | .GetIllustCommentsAsync(illustid, getparam("offset"), bool.Parse(getparam("include_total_comments")));
89 | }
90 | }
91 | catch
92 | {
93 | return toret;
94 | }
95 | nexturl = commentres.NextUrl?.ToString() ?? "";
96 | foreach (var recillust in commentres.Comments)
97 | {
98 | await Task.Run(() => pause.WaitOne());
99 | if (_emergencyStop)
100 | {
101 | nexturl = "";
102 | Clear();
103 | return new LoadMoreItemsResult() { Count = 0 };
104 | }
105 | IllustCommentItem recommendi = IllustCommentItem.FromObject(recillust);
106 | var recommendmodel = ViewModels.CommentViewModel.FromItem(recommendi);
107 | //查找是否存在子回复
108 | var children = from item
109 | in ChildrenComments
110 | where item.ParentID == recommendmodel.ID
111 | select item;
112 | children = children.ToList();
113 | if (children.Count() > 0)
114 | {
115 | //存在子回复
116 | recommendmodel.ChildrenComments = new ObservableCollection();
117 | foreach (var child in children)
118 | {
119 | if (child.ChildrenComments != null)
120 | {
121 | foreach (var childschild in child.ChildrenComments)
122 | {
123 | childschild.Comment = string.Format("Re: {0}: {1}",
124 | child.UserName, childschild.Comment);
125 | recommendmodel.ChildrenComments.Add(childschild);
126 | }
127 | child.ChildrenComments.Clear();
128 | child.ChildrenComments = null;
129 | GC.Collect();
130 | }
131 | recommendmodel.ChildrenComments.Insert(0, child);
132 | ChildrenComments.Remove(child);
133 | }
134 | }
135 | //检查自己是不是子回复
136 | if (recommendmodel.ParentID != -1)
137 | {
138 | //自己也是子回复
139 | ChildrenComments.Add(recommendmodel);
140 | }
141 | else
142 | {
143 | //自己并非子回复
144 | Add(recommendmodel);
145 | toret.Count++;
146 | }
147 | }
148 | return toret;
149 | }
150 | finally
151 | {
152 | _busy = false;
153 | _ = AvatarLoader.LoadAvatars();
154 | if (_emergencyStop)
155 | {
156 | AvatarLoader.EmergencyStop();
157 | nexturl = "";
158 | Clear();
159 | GC.Collect();
160 | }
161 | }
162 | }
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/PixivFSUWP/Data/Collections/FollowingIllustsCollection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using System.Text;
7 | using System.Threading;
8 | using System.Threading.Tasks;
9 | using Windows.Foundation;
10 | using Windows.UI.Xaml.Data;
11 | using System.Web;
12 | using Windows.Data.Json;
13 |
14 | namespace PixivFSUWP.Data.Collections
15 | {
16 | public class FollowingIllustsCollection : ObservableCollection, ISupportIncrementalLoading
17 | {
18 | string nexturl = "begin";
19 | bool _busy = false;
20 | bool _emergencyStop = false;
21 | EventWaitHandle pause = new ManualResetEvent(true);
22 |
23 | public bool HasMoreItems
24 | {
25 | get => !string.IsNullOrEmpty(nexturl);
26 | }
27 |
28 | public IAsyncOperation LoadMoreItemsAsync(uint count)
29 | {
30 | if (_busy)
31 | throw new InvalidOperationException("Only one operation in flight at a time");
32 | _busy = true;
33 | return AsyncInfo.Run((c) => LoadMoreItemsAsync(c, count));
34 | }
35 |
36 | public void StopLoading()
37 | {
38 | _emergencyStop = true;
39 | if (_busy)
40 | {
41 | ResumeLoading();
42 | }
43 | else
44 | {
45 | Clear();
46 | GC.Collect();
47 | }
48 | }
49 |
50 | public void PauseLoading()
51 | {
52 | pause.Reset();
53 | }
54 |
55 | public void ResumeLoading()
56 | {
57 | pause.Set();
58 | }
59 |
60 | protected async Task LoadMoreItemsAsync(CancellationToken c, uint count)
61 | {
62 | try
63 | {
64 | if (!HasMoreItems) return new LoadMoreItemsResult() { Count = 0 };
65 | LoadMoreItemsResult toret = new LoadMoreItemsResult() { Count = 0 };
66 | PixivCS.Objects.UserIllusts followingres = null;
67 | try
68 | {
69 | if (nexturl == "begin")
70 | followingres = await new PixivCS
71 | .PixivAppAPI(OverAll.GlobalBaseAPI)
72 | .GetIllustFollowAsync();
73 | else
74 | {
75 | Uri next = new Uri(nexturl);
76 | string getparam(string param) => HttpUtility.ParseQueryString(next.Query).Get(param);
77 | followingres = await new PixivCS
78 | .PixivAppAPI(OverAll.GlobalBaseAPI)
79 | .GetIllustFollowAsync(getparam("restrict"), getparam("offset"));
80 | }
81 | }
82 | catch
83 | {
84 | return toret;
85 | }
86 | nexturl = followingres.NextUrl?.ToString() ?? "";
87 | foreach (var recillust in followingres.Illusts)
88 | {
89 | await Task.Run(() => pause.WaitOne());
90 | if (_emergencyStop)
91 | {
92 | nexturl = "";
93 | Clear();
94 | return new LoadMoreItemsResult() { Count = 0 };
95 | }
96 | WaterfallItem recommendi = WaterfallItem.FromObject(recillust);
97 | var recommendmodel = ViewModels.WaterfallItemViewModel.FromItem(recommendi);
98 | await recommendmodel.LoadImageAsync();
99 | Add(recommendmodel);
100 | toret.Count++;
101 | }
102 | return toret;
103 | }
104 | finally
105 | {
106 | _busy = false;
107 | if (_emergencyStop)
108 | {
109 | nexturl = "";
110 | Clear();
111 | GC.Collect();
112 | }
113 | }
114 | }
115 | }
116 | }
117 |
118 |
--------------------------------------------------------------------------------
/PixivFSUWP/Data/Collections/RankingIllustsCollection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using System.Text;
7 | using System.Threading;
8 | using System.Threading.Tasks;
9 | using System.Web;
10 | using Windows.Data.Json;
11 | using Windows.Foundation;
12 | using Windows.UI.Xaml.Data;
13 |
14 | namespace PixivFSUWP.Data.Collections
15 | {
16 | public class RankingIllustsCollection : ObservableCollection, ISupportIncrementalLoading
17 | {
18 | string nexturl = "begin";
19 | bool _busy = false;
20 | bool _emergencyStop = false;
21 | EventWaitHandle pause = new ManualResetEvent(true);
22 |
23 | public bool HasMoreItems
24 | {
25 | get => !string.IsNullOrEmpty(nexturl);
26 | }
27 |
28 | public IAsyncOperation LoadMoreItemsAsync(uint count)
29 | {
30 | if (_busy)
31 | throw new InvalidOperationException("Only one operation in flight at a time");
32 | _busy = true;
33 | return AsyncInfo.Run((c) => LoadMoreItemsAsync(c, count));
34 | }
35 |
36 | public void StopLoading()
37 | {
38 | _emergencyStop = true;
39 | if (_busy)
40 | {
41 | ResumeLoading();
42 | }
43 | else
44 | {
45 | Clear();
46 | GC.Collect();
47 | }
48 | }
49 |
50 | public void PauseLoading()
51 | {
52 | pause.Reset();
53 | }
54 |
55 | public void ResumeLoading()
56 | {
57 | pause.Set();
58 | }
59 |
60 | protected async Task LoadMoreItemsAsync(CancellationToken c, uint count)
61 | {
62 | try
63 | {
64 | if (!HasMoreItems) return new LoadMoreItemsResult() { Count = 0 };
65 | LoadMoreItemsResult toret = new LoadMoreItemsResult() { Count = 0 };
66 | PixivCS.Objects.UserIllusts rankingres = null;
67 | try
68 | {
69 | if (nexturl == "begin")
70 | rankingres = await new PixivCS
71 | .PixivAppAPI(OverAll.GlobalBaseAPI)
72 | .GetIllustRankingAsync();
73 | else
74 | {
75 | Uri next = new Uri(nexturl);
76 | string getparam(string param) => HttpUtility.ParseQueryString(next.Query).Get(param);
77 | rankingres = await new PixivCS
78 | .PixivAppAPI(OverAll.GlobalBaseAPI)
79 | .GetIllustRankingAsync(Mode: getparam("mode"), Filter: getparam("filter"), Offset: getparam("offset"));
80 | }
81 | }
82 | catch
83 | {
84 | return toret;
85 | }
86 | nexturl = rankingres.NextUrl?.ToString() ?? "";
87 | foreach (var recillust in rankingres.Illusts)
88 | {
89 | await Task.Run(() => pause.WaitOne());
90 | if (_emergencyStop)
91 | {
92 | nexturl = "";
93 | Clear();
94 | return new LoadMoreItemsResult() { Count = 0 };
95 | }
96 | WaterfallItem recommendi = WaterfallItem.FromObject(recillust);
97 | var recommendmodel = ViewModels.WaterfallItemViewModel.FromItem(recommendi);
98 | await recommendmodel.LoadImageAsync();
99 | Add(recommendmodel);
100 | toret.Count++;
101 | }
102 | return toret;
103 | }
104 | finally
105 | {
106 | _busy = false;
107 | if (_emergencyStop)
108 | {
109 | nexturl = "";
110 | Clear();
111 | GC.Collect();
112 | }
113 | }
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/PixivFSUWP/Data/Collections/RecommendIllustsCollection.cs:
--------------------------------------------------------------------------------
1 | using PixivCS;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Collections.ObjectModel;
5 | using System.Linq;
6 | using System.Runtime.InteropServices.WindowsRuntime;
7 | using System.Text;
8 | using System.Threading;
9 | using System.Threading.Tasks;
10 | using Windows.Foundation;
11 | using Windows.UI.Xaml.Data;
12 | using System.Web;
13 | using Windows.Data.Json;
14 |
15 | namespace PixivFSUWP.Data.Collections
16 | {
17 | public class RecommendIllustsCollection : ObservableCollection, ISupportIncrementalLoading
18 | {
19 | string nexturl = "begin";
20 | bool _busy = false;
21 | bool _emergencyStop = false;
22 | EventWaitHandle pause = new ManualResetEvent(true);
23 |
24 | public bool HasMoreItems
25 | {
26 | get => !string.IsNullOrEmpty(nexturl);
27 | }
28 |
29 | public IAsyncOperation LoadMoreItemsAsync(uint count)
30 | {
31 | if (_busy)
32 | throw new InvalidOperationException("Only one operation in flight at a time");
33 | _busy = true;
34 | return AsyncInfo.Run((c) => LoadMoreItemsAsync(c, count));
35 | }
36 |
37 | public void StopLoading()
38 | {
39 | _emergencyStop = true;
40 | if (_busy)
41 | {
42 | ResumeLoading();
43 | }
44 | else
45 | {
46 | Clear();
47 | GC.Collect();
48 | }
49 | }
50 |
51 | public void PauseLoading()
52 | {
53 | pause.Reset();
54 | }
55 |
56 | public void ResumeLoading()
57 | {
58 | pause.Set();
59 | }
60 |
61 | protected async Task LoadMoreItemsAsync(CancellationToken c, uint count)
62 | {
63 | try
64 | {
65 | if (!HasMoreItems) return new LoadMoreItemsResult() { Count = 0 };
66 | LoadMoreItemsResult toret = new LoadMoreItemsResult() { Count = 0 };
67 | PixivCS.Objects.IllustRecommended recommendres = null;
68 | try
69 | {
70 | if (nexturl == "begin")
71 | recommendres = await new PixivAppAPI(OverAll.GlobalBaseAPI)
72 | .GetIllustRecommendedAsync();
73 | else
74 | {
75 | Uri next = new Uri(nexturl);
76 | string getparam(string param) => HttpUtility.ParseQueryString(next.Query).Get(param);
77 | recommendres = await new PixivAppAPI(OverAll.GlobalBaseAPI)
78 | .GetIllustRecommendedAsync(ContentType:
79 | getparam("content_type"),
80 | IncludeRankingLabel: bool.Parse(getparam("include_ranking_label")),
81 | Filter: getparam("filter"),
82 | MinBookmarkIDForRecentIllust: getparam("min_bookmark_id_for_recent_illust"),
83 | MaxBookmarkIDForRecommended: getparam("max_bookmark_id_for_recommend"),
84 | Offset: getparam("offset"),
85 | IncludeRankingIllusts: bool.Parse(getparam("include_ranking_illusts")),
86 | IncludePrivacyPolicy: getparam("include_privacy_policy"));
87 | }
88 | }
89 | catch
90 | {
91 | return toret;
92 | }
93 | nexturl = recommendres.NextUrl?.ToString() ?? "";
94 | foreach (var recillust in recommendres.Illusts)
95 | {
96 | await Task.Run(() => pause.WaitOne());
97 | if (_emergencyStop)
98 | {
99 | nexturl = "";
100 | Clear();
101 | return new LoadMoreItemsResult() { Count = 0 };
102 | }
103 | WaterfallItem recommendi = WaterfallItem.FromObject(recillust);
104 | var recommendmodel = ViewModels.WaterfallItemViewModel.FromItem(recommendi);
105 | await recommendmodel.LoadImageAsync();
106 | Add(recommendmodel);
107 | toret.Count++;
108 | }
109 | return toret;
110 | }
111 | finally
112 | {
113 | _busy = false;
114 | if (_emergencyStop)
115 | {
116 | nexturl = "";
117 | Clear();
118 | GC.Collect();
119 | }
120 | }
121 | }
122 | }
123 | }
124 |
125 |
--------------------------------------------------------------------------------
/PixivFSUWP/Data/Collections/SearchResultIllustsCollection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using System.Text;
7 | using System.Threading;
8 | using System.Threading.Tasks;
9 | using Windows.Foundation;
10 | using Windows.UI.Xaml.Data;
11 | using System.Web;
12 | using Windows.Data.Json;
13 |
14 | namespace PixivFSUWP.Data.Collections
15 | {
16 | public class SearchResultIllustsCollection : ObservableCollection, ISupportIncrementalLoading
17 | {
18 | readonly string word;
19 | readonly string searchTarget;
20 | readonly string sort;
21 | readonly string duration;
22 | string nexturl = "begin";
23 | bool _busy = false;
24 | bool _emergencyStop = false;
25 | EventWaitHandle pause = new ManualResetEvent(true);
26 |
27 | public SearchResultIllustsCollection(string Word, string SearchTarget = "partial_match_for_tags",
28 | string Sort = "date_desc", string Duration = null)
29 | {
30 | word = Word;
31 | searchTarget = SearchTarget;
32 | sort = Sort;
33 | duration = null;
34 | }
35 |
36 | public bool HasMoreItems
37 | {
38 | get => !string.IsNullOrEmpty(nexturl);
39 | }
40 |
41 | public IAsyncOperation LoadMoreItemsAsync(uint count)
42 | {
43 | if (_busy)
44 | throw new InvalidOperationException("Only one operation in flight at a time");
45 | _busy = true;
46 | return AsyncInfo.Run((c) => LoadMoreItemsAsync(c, count));
47 | }
48 |
49 | public void StopLoading()
50 | {
51 | _emergencyStop = true;
52 | if (_busy)
53 | {
54 | ResumeLoading();
55 | }
56 | else
57 | {
58 | Clear();
59 | GC.Collect();
60 | }
61 | }
62 |
63 | public void PauseLoading()
64 | {
65 | pause.Reset();
66 | }
67 |
68 | public void ResumeLoading()
69 | {
70 | pause.Set();
71 | }
72 |
73 | protected async Task LoadMoreItemsAsync(CancellationToken c, uint count)
74 | {
75 | try
76 | {
77 | if (!HasMoreItems) return new LoadMoreItemsResult() { Count = 0 };
78 | LoadMoreItemsResult toret = new LoadMoreItemsResult() { Count = 0 };
79 | PixivCS.Objects.SearchIllustResult searchres = null;
80 | try
81 | {
82 | if (nexturl == "begin")
83 | searchres = await new PixivCS
84 | .PixivAppAPI(OverAll.GlobalBaseAPI)
85 | .GetSearchIllustAsync(word, searchTarget, sort, duration);
86 | else
87 | {
88 | Uri next = new Uri(nexturl);
89 | string getparam(string param) => HttpUtility.ParseQueryString(next.Query).Get(param);
90 | var test = getparam("duration");
91 | searchres = await new PixivCS
92 | .PixivAppAPI(OverAll.GlobalBaseAPI)
93 | .GetSearchIllustAsync(getparam("word"), getparam("search_target"),
94 | getparam("sort"), getparam("duration"), getparam("filter"), getparam("offset"));
95 | }
96 | }
97 | catch
98 | {
99 | return toret;
100 | }
101 | nexturl = searchres.NextUrl?.ToString() ?? "";
102 | foreach (var recillust in searchres.Illusts)
103 | {
104 | await Task.Run(() => pause.WaitOne());
105 | if (_emergencyStop)
106 | {
107 | nexturl = "";
108 | Clear();
109 | return new LoadMoreItemsResult() { Count = 0 };
110 | }
111 | WaterfallItem recommendi = WaterfallItem.FromObject(recillust);
112 | var recommendmodel = ViewModels.WaterfallItemViewModel.FromItem(recommendi);
113 | await recommendmodel.LoadImageAsync();
114 | Add(recommendmodel);
115 | toret.Count++;
116 | }
117 | return toret;
118 | }
119 | finally
120 | {
121 | _busy = false;
122 | if (_emergencyStop)
123 | {
124 | nexturl = "";
125 | Clear();
126 | GC.Collect();
127 | }
128 | }
129 | }
130 | }
131 | }
132 |
133 |
--------------------------------------------------------------------------------
/PixivFSUWP/Data/Collections/UserIllustsCollection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using System.Text;
7 | using System.Threading;
8 | using System.Threading.Tasks;
9 | using System.Web;
10 | using Windows.Data.Json;
11 | using Windows.Foundation;
12 | using Windows.UI.Xaml.Data;
13 |
14 | namespace PixivFSUWP.Data.Collections
15 | {
16 | public class UserIllustsCollection : ObservableCollection, ISupportIncrementalLoading
17 | {
18 | readonly string userID;
19 | string nexturl = "begin";
20 | bool _busy = false;
21 | bool _emergencyStop = false;
22 | EventWaitHandle pause = new ManualResetEvent(true);
23 |
24 | public UserIllustsCollection(string UserID)
25 | {
26 | userID = UserID;
27 | }
28 |
29 | public bool HasMoreItems
30 | {
31 | get => !string.IsNullOrEmpty(nexturl);
32 | }
33 |
34 | public IAsyncOperation LoadMoreItemsAsync(uint count)
35 | {
36 | if (_busy)
37 | throw new InvalidOperationException("Only one operation in flight at a time");
38 | _busy = true;
39 | return AsyncInfo.Run((c) => LoadMoreItemsAsync(c, count));
40 | }
41 |
42 | public void StopLoading()
43 | {
44 | _emergencyStop = true;
45 | if (_busy)
46 | {
47 | ResumeLoading();
48 | }
49 | else
50 | {
51 | Clear();
52 | GC.Collect();
53 | }
54 | }
55 |
56 | public void PauseLoading()
57 | {
58 | pause.Reset();
59 | }
60 |
61 | public void ResumeLoading()
62 | {
63 | pause.Set();
64 | }
65 |
66 | protected async Task LoadMoreItemsAsync(CancellationToken c, uint count)
67 | {
68 | try
69 | {
70 | if (!HasMoreItems) return new LoadMoreItemsResult() { Count = 0 };
71 | LoadMoreItemsResult toret = new LoadMoreItemsResult() { Count = 0 };
72 | PixivCS.Objects.UserIllusts illustsres = null;
73 | try
74 | {
75 | if (nexturl == "begin")
76 | illustsres = await new PixivCS
77 | .PixivAppAPI(OverAll.GlobalBaseAPI)
78 | .GetUserIllustsAsync(userID);
79 | else
80 | {
81 | Uri next = new Uri(nexturl);
82 | string getparam(string param) => HttpUtility.ParseQueryString(next.Query).Get(param);
83 | illustsres = await new PixivCS
84 | .PixivAppAPI(OverAll.GlobalBaseAPI)
85 | .GetUserIllustsAsync(getparam("user_id"), getparam("type"), getparam("filter"), getparam("offset"));
86 | }
87 | }
88 | catch
89 | {
90 | return toret;
91 | }
92 | nexturl = illustsres.NextUrl?.ToString() ?? "";
93 | foreach (var recillust in illustsres.Illusts)
94 | {
95 | await Task.Run(() => pause.WaitOne());
96 | if (_emergencyStop)
97 | {
98 | nexturl = "";
99 | Clear();
100 | return new LoadMoreItemsResult() { Count = 0 };
101 | }
102 | WaterfallItem recommendi = WaterfallItem.FromObject(recillust);
103 | var recommendmodel = ViewModels.WaterfallItemViewModel.FromItem(recommendi);
104 | await recommendmodel.LoadImageAsync();
105 | Add(recommendmodel);
106 | toret.Count++;
107 | }
108 | return toret;
109 | }
110 | finally
111 | {
112 | _busy = false;
113 | if (_emergencyStop)
114 | {
115 | nexturl = "";
116 | Clear();
117 | GC.Collect();
118 | }
119 | }
120 | }
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/PixivFSUWP/Data/CommentAvatarLoader.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace PixivFSUWP.Data
9 | {
10 | public class CommentAvatarLoader
11 | {
12 | private bool isBusy = false;
13 | private bool emergencyStop = false;
14 | private int currentIndex = 0;
15 | private ObservableCollection collection;
16 |
17 | public CommentAvatarLoader(ObservableCollection Collection) => collection = Collection;
18 |
19 | public async Task LoadAvatars()
20 | {
21 | if (isBusy) return;
22 | isBusy = true;
23 | try
24 | {
25 | while (currentIndex + 1 <= collection.Count)
26 | {
27 | if (emergencyStop)
28 | {
29 | collection = null;
30 | return;
31 | }
32 | await collection[currentIndex].LoadAvatarAsync();
33 | if (collection[currentIndex].ChildrenComments != null)
34 | {
35 | foreach (var child in collection[currentIndex].ChildrenComments)
36 | {
37 | await child.LoadAvatarAsync();
38 | }
39 | }
40 | currentIndex++;
41 | }
42 | }
43 | finally
44 | {
45 | isBusy = false;
46 | }
47 | }
48 |
49 | public void EmergencyStop() => emergencyStop = true;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/PixivFSUWP/Data/Contributor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.Data.Json;
7 |
8 | namespace PixivFSUWP.Data
9 | {
10 | public enum Contribution
11 | {
12 | code, doc, translation, bug, idea, unknown
13 | }
14 |
15 | public class Contributor
16 | {
17 | public string AvatarUrl { get; set; }
18 | public string DisplayName { get; set; }
19 | public string Account { get; set; }
20 | public string ProfileUrl { get; set; }
21 | public List Contributions { get; set; }
22 |
23 | //由字符串返回Contribution枚举
24 | private static Contribution stringToContribution(string source)
25 | {
26 | switch (source)
27 | {
28 | case "doc":
29 | return Contribution.doc;
30 | case "translation":
31 | return Contribution.translation;
32 | case "code":
33 | return Contribution.code;
34 | case "bug":
35 | return Contribution.bug;
36 | case "ideas":
37 | return Contribution.idea;
38 | default:
39 | return Contribution.unknown;
40 | }
41 | }
42 |
43 | public static Contributor FromJsonValue(JsonObject Source)
44 | {
45 | Contributor toret = new Contributor();
46 | toret.Account = Source["login"].TryGetString();
47 | toret.DisplayName = Source["name"].TryGetString();
48 | toret.AvatarUrl = Source["avatar_url"].TryGetString();
49 | toret.ProfileUrl = Source["profile"].TryGetString();
50 | toret.Contributions = new List();
51 | var contributions = Source["contributions"].GetArray();
52 | foreach (var contribution in contributions)
53 | toret.Contributions.Add(stringToContribution(contribution.TryGetString()));
54 | return toret;
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/PixivFSUWP/Data/ContributorsHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Net.Http;
7 | using Windows.Data.Json;
8 |
9 | namespace PixivFSUWP.Data
10 | {
11 | public static class ContributorsHelper
12 | {
13 | public async static Task> GetContributorsAsync()
14 | {
15 | try
16 | {
17 | List toret = new List();
18 | HttpClient client = new HttpClient();
19 | var res = await client.GetAsync("https://raw.githubusercontent.com/tobiichiamane/pixivfs-uwp/master/.all-contributorsrc");
20 | var json = JsonObject.Parse(await res.Content.ReadAsStringAsync());
21 | var array = json["contributors"].GetArray();
22 | foreach (var i in array)
23 | toret.Add(Contributor.FromJsonValue(i.GetObject()));
24 | return toret;
25 | }
26 | catch
27 | {
28 | return null;
29 | }
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/PixivFSUWP/Data/CurrentUser.cs:
--------------------------------------------------------------------------------
1 |
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Windows.Data.Json;
8 |
9 | namespace PixivFSUWP.Data
10 | {
11 | public class CurrentUser
12 | {
13 | public int ID { get; set; }
14 | public string Username { get; set; }
15 | public string UserAccount { get; set; }
16 | public string Email { get; set; }
17 | public bool IsMailAuthorized { get; set; }
18 | public bool IsPremium { get; set; }
19 | public string Avatar16 { get; set; }
20 | public string Avatar50 { get; set; }
21 | public string Avatar170 { get; set; }
22 |
23 | public static CurrentUser FromObject(PixivCS.Objects.ResponseUser Source)
24 | {
25 | CurrentUser toret = new CurrentUser();
26 | toret.ID = Convert.ToInt32(Source.Id);
27 | toret.Username = Source.Name;
28 | toret.UserAccount = Source.Account;
29 | toret.Email = Source.MailAddress;
30 | toret.IsMailAuthorized = Source.IsMailAuthorized;
31 | toret.IsPremium = Source.IsPremium;
32 | toret.Avatar16 = Source.ProfileImageUrls.Px16X16?.ToString() ?? "";
33 | toret.Avatar50 = Source.ProfileImageUrls.Px50X50?.ToString() ?? "";
34 | toret.Avatar170 = Source.ProfileImageUrls.Px170X170?.ToString() ?? "";
35 | return toret;
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/PixivFSUWP/Data/DownloadManager.cs:
--------------------------------------------------------------------------------
1 | using Lumia.Imaging.Compositing;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Collections.ObjectModel;
5 | using System.ComponentModel;
6 | using System.IO;
7 | using System.Linq;
8 | using System.Text;
9 | using System.Threading;
10 | using System.Threading.Tasks;
11 | using Windows.Storage;
12 |
13 | namespace PixivFSUWP.Data
14 | {
15 | //下载完成时的事件参数
16 | public class DownloadCompletedEventArgs : EventArgs
17 | {
18 | public bool HasError { get; set; }
19 | }
20 |
21 | public class DownloadJob : INotifyPropertyChanged
22 | {
23 | public string Title { get; }
24 | public string Uri { get; }
25 | public string FilePath { get; }
26 |
27 | private int progress;
28 | public int Progress
29 | {
30 | get => progress;
31 | private set
32 | {
33 | progress = value;
34 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Progress"));
35 | }
36 | }
37 |
38 | public DownloadJob(string Title, string Uri, string FilePath)
39 | {
40 | this.Title = Title;
41 | this.Uri = Uri;
42 | this.FilePath = FilePath;
43 | Progress = 0;
44 | Downloading = false;
45 | }
46 |
47 | //下载状态
48 | public bool Downloading { get; private set; }
49 |
50 | //用于暂停的ManualResetEvent
51 | ManualResetEvent pauseEvent = new ManualResetEvent(true);
52 |
53 | //用于取消任务的CancellationTokenSource
54 | CancellationTokenSource tokenSource = new CancellationTokenSource();
55 |
56 | //下载完成时的事件
57 | public event Action DownloadCompleted;
58 |
59 | //通知属性更改
60 | public event PropertyChangedEventHandler PropertyChanged;
61 |
62 | //进行下载
63 | public async Task Download()
64 | {
65 | if (!Downloading)
66 | {
67 | Downloading = true;
68 | using (var memStream = await OverAll.DownloadImage(Uri, tokenSource.Token, pauseEvent, async (loaded, length) =>
69 | {
70 | await Task.Run(() =>
71 | {
72 | Progress = (int)(loaded * 100 / length);
73 | });
74 | }))
75 | {
76 | if (tokenSource.IsCancellationRequested) return;
77 | var file = await StorageFile.GetFileFromPathAsync(FilePath);
78 | CachedFileManager.DeferUpdates(file);
79 | using (var fileStream = await file.OpenAsync(FileAccessMode.ReadWrite))
80 | {
81 | await memStream.CopyToAsync(fileStream.AsStream());
82 | }
83 | var result = await CachedFileManager.CompleteUpdatesAsync(file);
84 | if (result == Windows.Storage.Provider.FileUpdateStatus.Complete)
85 | {
86 | DownloadCompleted?.Invoke(this, new DownloadCompletedEventArgs() { HasError = false });
87 | }
88 | else
89 | {
90 | DownloadCompleted?.Invoke(this, new DownloadCompletedEventArgs() { HasError = true });
91 | }
92 | }
93 | }
94 | }
95 |
96 | //暂停下载
97 | public void Pause()
98 | {
99 | pauseEvent.Reset();
100 | }
101 |
102 | //恢复下载
103 | public void Resume()
104 | {
105 | pauseEvent.Set();
106 | }
107 |
108 | //取消下载
109 | public void Cancel()
110 | {
111 | tokenSource.Cancel();
112 | }
113 | }
114 |
115 | //静态的下载管理器。应用程序不会有多个下载管理器实例。
116 | public static class DownloadManager
117 | {
118 | //下载任务列表
119 | public static ObservableCollection DownloadJobs = new ObservableCollection();
120 |
121 | //添加下载任务
122 | public static void NewJob(string Title, string Uri, string FilePath)
123 | {
124 | var job = new DownloadJob(Title, Uri, FilePath);
125 | job.DownloadCompleted += Job_DownloadCompleted;
126 | DownloadJobs.Add(job);
127 | _ = job.Download();
128 | }
129 |
130 | //有任务下载完成时的事件
131 | public static event Action DownloadCompleted;
132 |
133 | //下载完成时
134 | private static void Job_DownloadCompleted(DownloadJob source, DownloadCompletedEventArgs args)
135 | {
136 | DownloadJobs.Remove(source);
137 | DownloadCompleted?.Invoke(source.Title, args.HasError);
138 | }
139 |
140 | //移除下载任务
141 | public static void RemoveJob(int Index)
142 | {
143 | var job = DownloadJobs[Index];
144 | job.DownloadCompleted -= Job_DownloadCompleted;
145 | job.Cancel();
146 | DownloadJobs.Remove(job);
147 | }
148 |
149 | //移除下载任务
150 | public static void RemoveJob(DownloadJob Job)
151 | {
152 | Job.DownloadCompleted -= Job_DownloadCompleted;
153 | Job.Cancel();
154 | DownloadJobs.Remove(Job);
155 | }
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/PixivFSUWP/Data/IllustCommentItem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.Data.Json;
7 |
8 | namespace PixivFSUWP.Data
9 | {
10 | public class IllustCommentItem
11 | {
12 | public int ID { get; set; }
13 | public string Comment { get; set; }
14 | public string DateTime { get; set; }
15 | public string UserName { get; set; }
16 | public string UserAccount { get; set; }
17 | public string AvatarUrl { get; set; }
18 | public int ParentCommentID { get; set; }
19 |
20 | public static IllustCommentItem FromObject(PixivCS.Objects.Comment Source)
21 | {
22 | IllustCommentItem toret = new IllustCommentItem();
23 | toret.ID = (int)Source.Id;
24 | toret.Comment = Source.CommentComment;
25 | toret.DateTime = Source.Date;
26 | toret.UserName = Source.User.Name;
27 | toret.UserAccount = Source.User.Account;
28 | toret.AvatarUrl = Source.User.ProfileImageUrls.Medium?.ToString() ?? "";
29 | if (Source.ParentComment.CommentComment != null)
30 | {
31 | //有父级评论
32 | toret.ParentCommentID = (int)Source.ParentComment.Id;
33 | }
34 | else
35 | {
36 | toret.ParentCommentID = -1;
37 | }
38 | return toret;
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/PixivFSUWP/Data/IllustDetail.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.Data.Json;
7 |
8 | namespace PixivFSUWP.Data
9 | {
10 | public class IllustDetail
11 | {
12 | public int IllustID { get; set; }
13 | public string Title { get; set; }
14 | public string Type { get; set; }
15 | public string Caption { get; set; }
16 | public int AuthorID { get; set; }
17 | public string Author { get; set; }
18 | public string AuthorAccount { get; set; }
19 | public string AuthorAvatarUrl { get; set; }
20 | public bool IsUserFollowed { get; set; }
21 | public List Tags { get; set; }
22 | public List Tools { get; set; }
23 | public string CreateDate { get; set; }
24 | public int Width { get; set; }
25 | public int Height { get; set; }
26 | public int SanityLevel { get; set; }
27 | public string MediumUrl { get; set; }
28 | public List OriginalUrls { get; set; }
29 | public int TotalView { get; set; }
30 | public int TotalBookmarks { get; set; }
31 | public int TotalComments { get; set; }
32 | public bool IsBookmarked { get; set; }
33 |
34 | public static IllustDetail FromObject(PixivCS.Objects.IllustDetail Source)
35 | {
36 | IllustDetail toret = new IllustDetail();
37 | toret.IllustID = (int)Source.Illust.Id;
38 | toret.Title = Source.Illust.Title;
39 | toret.Type = Source.Illust.Type;
40 | toret.Caption = Source.Illust.Caption;
41 | toret.AuthorID = (int)Source.Illust.User.Id;
42 | toret.Author = Source.Illust.User.Name;
43 | toret.AuthorAccount = Source.Illust.User.Account;
44 | toret.AuthorAvatarUrl = Source.Illust.User.ProfileImageUrls.Medium?.ToString() ?? "";
45 | toret.IsUserFollowed = Source.Illust.User.IsFollowed.HasValue ? Source.Illust.User.IsFollowed.Value : false;
46 | var tags = Source.Illust.Tags;
47 | toret.Tags = new List();
48 | foreach (var tag in tags)
49 | toret.Tags.Add(tag.Name);
50 | var tools = Source.Illust.Tools;
51 | toret.Tools = new List();
52 | foreach (var tool in tools)
53 | toret.Tools.Add(tool);
54 | toret.CreateDate = Source.Illust.CreateDate;
55 | toret.MediumUrl = Source.Illust.ImageUrls.SquareMedium?.ToString() ?? "";
56 | var pgCount = (int)Source.Illust.PageCount;
57 | toret.OriginalUrls = new List();
58 | if (pgCount == 1) toret.OriginalUrls.Add(Source.Illust.MetaSinglePage.OriginalImageUrl?.ToString());
59 | else
60 | {
61 | var pages = Source.Illust.MetaPages;
62 | foreach (var page in pages)
63 | toret.OriginalUrls.Add(page.ImageUrls.Original?.ToString());
64 | }
65 | toret.Width = (int)Source.Illust.Width;
66 | toret.Height = (int)Source.Illust.Height;
67 | toret.SanityLevel = (int)Source.Illust.SanityLevel;
68 | toret.TotalView = (int)Source.Illust.TotalView;
69 | toret.TotalBookmarks = (int)Source.Illust.TotalBookmarks;
70 | toret.IsBookmarked = Source.Illust.IsBookmarked;
71 | toret.TotalComments = (int)Source.Illust.TotalComments;
72 | return toret;
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/PixivFSUWP/Data/Ugoira.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.Graphics.Imaging;
7 | using Windows.UI.Xaml.Media.Imaging;
8 |
9 | namespace PixivFSUWP.Data
10 | {
11 | public class Ugoira : IDisposable
12 | {
13 | public struct Frame
14 | {
15 | public SoftwareBitmap Image;
16 | public int Delay;
17 | }
18 |
19 | public List Frames { get; } = new List();
20 |
21 | public void Dispose()
22 | {
23 | foreach(var i in Frames)
24 | {
25 | i.Image.Dispose();
26 | }
27 | Frames.Clear();
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/PixivFSUWP/Data/UgoiraHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.IO.Compression;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using PixivCS;
9 | using Windows.Graphics.Imaging;
10 | using Windows.UI.Xaml.Media.Imaging;
11 |
12 | namespace PixivFSUWP.Data
13 | {
14 | public static class UgoiraHelper
15 | {
16 | public static async Task GetUgoiraAsync(string IllustID)
17 | {
18 | List framefiles = new List();
19 | Dictionary framedelays = new Dictionary();
20 | Dictionary frameimgs = new Dictionary();
21 | try
22 | {
23 | var res = await new PixivAppAPI(OverAll.GlobalBaseAPI).GetUgoiraMetadataAsync(IllustID);
24 | if (res.UgoiraMetadataUgoiraMetadata == null) return null;
25 | var framesarray = res.UgoiraMetadataUgoiraMetadata.Frames;
26 | foreach (var i in framesarray)
27 | {
28 | var file = i.File;
29 | framefiles.Add(file);
30 | framedelays.Add(file, (int)i.Delay);
31 | }
32 | var zipurl = res.UgoiraMetadataUgoiraMetadata.ZipUrls.Medium?.ToString() ?? "";
33 | using (var zipfile = await OverAll.DownloadImage(zipurl))
34 | {
35 | using (ZipArchive ziparc = new ZipArchive(zipfile, ZipArchiveMode.Read))
36 | {
37 | foreach (var entry in ziparc.Entries)
38 | {
39 | var file = entry.FullName;
40 | using (var memStream = new MemoryStream())
41 | {
42 | await entry.Open().CopyToAsync(memStream);
43 | memStream.Position = 0;
44 | BitmapDecoder decoder = await BitmapDecoder.CreateAsync(memStream.AsRandomAccessStream());
45 | frameimgs.Add(file, await decoder.GetSoftwareBitmapAsync());
46 | }
47 | }
48 | }
49 | }
50 | Ugoira toret = new Ugoira();
51 | foreach (var i in framefiles)
52 | toret.Frames.Add(new Ugoira.Frame() { Image = frameimgs[i], Delay = framedelays[i] });
53 | return toret;
54 | }
55 | finally
56 | {
57 | framefiles.Clear();
58 | framedelays.Clear();
59 | frameimgs.Clear();
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/PixivFSUWP/Data/UserDetail.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection.PortableExecutable;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Windows.Data.Json;
8 |
9 | namespace PixivFSUWP.Data
10 | {
11 | public class UserDetail
12 | {
13 | public int ID { get; set; }
14 | public string Name { get; set; }
15 | public string Account { get; set; }
16 | public string AvatarUrl { get; set; }
17 | public string Comment { get; set; }
18 | public bool IsFollowed { get; set; }
19 | public string WebPage { get; set; }
20 | public string Gender { get; set; }
21 | public string Birth { get; set; }
22 | public string BirthDay { get; set; }
23 | public int BirthYear { get; set; }
24 | public string Region { get; set; }
25 | public int AddressID { get; set; }
26 | public string CountryCode { get; set; }
27 | public string Job { get; set; }
28 | public int JobID { get; set; }
29 | public int TotalFollowUsers { get; set; }
30 | public int TotalMyPixivUsers { get; set; }
31 | public int TotalIllusts { get; set; }
32 | public int TotalManga { get; set; }
33 | public int TotalNovels { get; set; }
34 | public int TotalIllustBookmarksPublic { get; set; }
35 | public int TotalIllustSeries { get; set; }
36 | public int TotalNovelSeries { get; set; }
37 | public string BackgroundImage { get; set; }
38 | public string TwitterAccount { get; set; }
39 | public string TwitterUrl { get; set; }
40 | public string PawooUrl { get; set; }
41 | public bool IsPremium { get; set; }
42 | public bool IsUsingCustomProfileImage { get; set; }
43 | public string GenderPublicity { get; set; }
44 | public string RegionPublicity { get; set; }
45 | public string BirthDayPublicity { get; set; }
46 | public string BirthYearPublicity { get; set; }
47 | public string JobPublicity { get; set; }
48 | public bool Pawoo { get; set; }
49 | public string PC { get; set; }
50 | public string Monitor { get; set; }
51 | public string Tool { get; set; }
52 | public string Scanner { get; set; }
53 | public string Tablet { get; set; }
54 | public string Mouse { get; set; }
55 | public string Printer { get; set; }
56 | public string Desktop { get; set; }
57 | public string Music { get; set; }
58 | public string Desk { get; set; }
59 | public string Chair { get; set; }
60 | public string WorkspaceComment { get; set; }
61 | public string WorkspaceImageUrl { get; set; }
62 |
63 | public static UserDetail FromObject(PixivCS.Objects.UserDetail Source)
64 | {
65 | UserDetail toret = new UserDetail();
66 | var user = Source.User;
67 | toret.ID = (int)user.Id;
68 | toret.Name = user.Name;
69 | toret.Account = user.Account;
70 | toret.AvatarUrl = user.ProfileImageUrls.Medium?.ToString() ?? "";
71 | toret.Comment = user.Comment;
72 | toret.IsFollowed = user.IsFollowed.HasValue ? user.IsFollowed.Value : false;
73 | var profile = Source.Profile;
74 | toret.WebPage = profile.Webpage?.ToString() ?? "";
75 | toret.Gender = profile.Gender;
76 | toret.Birth = profile.Birth;
77 | toret.BirthDay = profile.BirthDay;
78 | toret.BirthYear = (int)profile.BirthYear;
79 | toret.Region = profile.Region;
80 | toret.AddressID = (int)profile.AddressId;
81 | toret.CountryCode = profile.CountryCode;
82 | toret.Job = profile.Job;
83 | toret.JobID = (int)profile.JobId;
84 | toret.TotalFollowUsers = (int)profile.TotalFollowUsers;
85 | toret.TotalMyPixivUsers = (int)profile.TotalMypixivUsers;
86 | toret.TotalIllusts = (int)profile.TotalIllusts;
87 | toret.TotalManga = (int)profile.TotalManga;
88 | toret.TotalNovels = (int)profile.TotalNovels;
89 | toret.TotalIllustBookmarksPublic = (int)profile.TotalIllustBookmarksPublic;
90 | toret.TotalIllustSeries = (int)profile.TotalIllustSeries;
91 | toret.TotalNovelSeries = (int)profile.TotalNovelSeries;
92 | toret.BackgroundImage = profile.BackgroundImageUrl?.ToString() ?? "";
93 | toret.TwitterAccount = profile.TwitterAccount;
94 | toret.TwitterUrl = profile.TwitterUrl?.ToString() ?? "";
95 | toret.PawooUrl = profile.PawooUrl?.ToString() ?? "";
96 | toret.IsPremium = profile.IsPremium;
97 | toret.IsUsingCustomProfileImage = profile.IsUsingCustomProfileImage;
98 | var profile_publicity = Source.ProfilePublicity;
99 | toret.GenderPublicity = profile_publicity.Gender;
100 | toret.RegionPublicity = profile_publicity.Region;
101 | toret.BirthDayPublicity = profile_publicity.BirthDay;
102 | toret.BirthYearPublicity = profile_publicity.BirthYear;
103 | toret.JobPublicity = profile_publicity.Job;
104 | toret.Pawoo = profile_publicity.Pawoo;
105 | var workspace = Source.Workspace;
106 | toret.PC = workspace.Pc;
107 | toret.Monitor = workspace.Monitor;
108 | toret.Tool = workspace.Tool;
109 | toret.Scanner = workspace.Scanner;
110 | toret.Tablet = workspace.Tablet;
111 | toret.Mouse = workspace.Mouse;
112 | toret.Printer = workspace.Printer;
113 | toret.Desktop = workspace.Desktop;
114 | toret.Music = workspace.Music;
115 | toret.Desk = workspace.Desk;
116 | toret.Chair = workspace.Chair;
117 | toret.WorkspaceComment = workspace.Comment;
118 | toret.WorkspaceImageUrl = workspace.WorkspaceImageUrl?.ToString() ?? "";
119 | return toret;
120 | }
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/PixivFSUWP/Data/WaterfallItem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.Data.Json;
7 |
8 | namespace PixivFSUWP.Data
9 | {
10 | public class WaterfallItem
11 | {
12 | public int Id { get; set; }
13 | public string Title { get; set; }
14 | public string Author { get; set; }
15 | public string ImageUri { get; set; }
16 | public int Stars { get; set; }
17 | public int Pages { get; set; }
18 | public bool IsBookmarked { get; set; }
19 | public int Width { get; set; }
20 | public int Height { get; set; }
21 |
22 | public static WaterfallItem FromObject(PixivCS.Objects.UserPreviewIllust Source)
23 | {
24 | var toret = new WaterfallItem();
25 | toret.Id = (int)Source.Id;
26 | toret.Title = Source.Title;
27 | toret.Author = Source.User.Name;
28 | toret.ImageUri = Source.ImageUrls.Medium?.ToString() ?? "";
29 | toret.Stars = (int)Source.TotalBookmarks;
30 | toret.Pages = (int)Source.PageCount;
31 | toret.IsBookmarked = Source.IsBookmarked;
32 | toret.Width = (int)Source.Width;
33 | toret.Height = (int)Source.Height;
34 | return toret;
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/PixivFSUWP/DownloadManager.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/PixivFSUWP/DownloadManager.xaml.cs:
--------------------------------------------------------------------------------
1 | using PixivFSUWP.Data;
2 | using PixivFSUWP.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Runtime.InteropServices.WindowsRuntime;
8 | using Windows.Foundation;
9 | using Windows.Foundation.Collections;
10 | using Windows.UI.Xaml;
11 | using Windows.UI.Xaml.Controls;
12 | using Windows.UI.Xaml.Controls.Primitives;
13 | using Windows.UI.Xaml.Data;
14 | using Windows.UI.Xaml.Input;
15 | using Windows.UI.Xaml.Media;
16 | using Windows.UI.Xaml.Navigation;
17 |
18 | // https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“空白页”项模板
19 |
20 | namespace PixivFSUWP
21 | {
22 | ///
23 | /// 可用于自身或导航至 Frame 内部的空白页。
24 | ///
25 | public sealed partial class DownloadManager : Page, IGoBackFlag
26 | {
27 | bool _backflag = false;
28 |
29 | public DownloadManager()
30 | {
31 | this.InitializeComponent();
32 | }
33 |
34 | public void SetBackFlag(bool value)
35 | {
36 | _backflag = value;
37 | }
38 |
39 | protected override void OnNavigatedTo(NavigationEventArgs e)
40 | {
41 | base.OnNavigatedTo(e);
42 | OverAll.TheMainPage.SelectNavPlaceholder(OverAll.GetResourceString("DownloadsPlain"));
43 | NavControl.SelectedItem = NavControl.MenuItems[1];
44 | }
45 |
46 | protected override void OnNavigatedFrom(NavigationEventArgs e)
47 | {
48 | if (!_backflag)
49 | {
50 | Backstack.Default.Push(typeof(DownloadManager), null);
51 | ((Frame.Parent as Grid)?.Parent as MainPage)?.UpdateNavButtonState();
52 | }
53 | base.OnNavigatedFrom(e);
54 | }
55 |
56 | private void NavControl_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args)
57 | {
58 | if (args.SelectedItem == NavControl.MenuItems[1])
59 | {
60 | //选择了“下载中”
61 | ContentFrame.Navigate(typeof(DownloadingPage));
62 | }
63 | else
64 | {
65 | //选择了“下载完毕”
66 | }
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/PixivFSUWP/DownloadingPage.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/PixivFSUWP/DownloadingPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 |
16 | // https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“空白页”项模板
17 |
18 | namespace PixivFSUWP
19 | {
20 | ///
21 | /// 可用于自身或导航至 Frame 内部的空白页。
22 | ///
23 | public sealed partial class DownloadingPage : Page
24 | {
25 | public DownloadingPage()
26 | {
27 | this.InitializeComponent();
28 | //直接进行数据绑定
29 | lstDownloading.ItemsSource = Data.DownloadManager.DownloadJobs;
30 | //!测试数据!
31 | Data.DownloadManager.DownloadJobs.Add(new Data.DownloadJob("Foo1", "i.pximg.net/114514", "d:\\14514.png"));
32 | Data.DownloadManager.DownloadJobs.Add(new Data.DownloadJob("Foo2", "i.pximg.net/98e", "d:\\98e.png"));
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/PixivFSUWP/Interfaces/IGoBackFlag.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace PixivFSUWP.Interfaces
8 | {
9 | public interface IGoBackFlag
10 | {
11 | void SetBackFlag(bool value);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/PixivFSUWP/LoginPage.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
76 |
77 |
78 |
79 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
136 |
137 |
138 |
146 |
147 |
148 |
149 |
--------------------------------------------------------------------------------
/PixivFSUWP/LoginPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.ApplicationModel.Core;
7 | using Windows.Foundation;
8 | using Windows.Foundation.Collections;
9 | using Windows.System;
10 | using Windows.UI;
11 | using Windows.UI.ViewManagement;
12 | using Windows.UI.Xaml;
13 | using Windows.UI.Xaml.Controls;
14 | using Windows.UI.Xaml.Controls.Primitives;
15 | using Windows.UI.Xaml.Data;
16 | using Windows.UI.Xaml.Input;
17 | using Windows.UI.Xaml.Media;
18 | using Windows.UI.Xaml.Navigation;
19 | using System.Threading.Tasks;
20 | using System.Diagnostics;
21 | using Windows.Security.Credentials;
22 | using PixivCS;
23 | using static PixivFSUWP.Data.OverAll;
24 | using Windows.Data.Json;
25 |
26 | // https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“空白页”项模板
27 |
28 | namespace PixivFSUWP
29 | {
30 | ///
31 | /// 可用于自身或导航至 Frame 内部的空白页。
32 | ///
33 | public sealed partial class LoginPage : Page
34 | {
35 | private string username = null;
36 | private string password = null;
37 | private string refreshToken = null;
38 | private bool useToken = false;
39 | private bool directConnetion = false;
40 | private bool isCancelled = false;
41 | Windows.Storage.ApplicationDataContainer localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
42 |
43 | public LoginPage()
44 | {
45 | this.InitializeComponent();
46 | CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true;
47 | var view = ApplicationView.GetForCurrentView();
48 | view.TitleBar.ButtonBackgroundColor = Colors.Transparent;
49 | view.TitleBar.ButtonForegroundColor = Colors.White;
50 | view.TitleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
51 | view.TitleBar.ButtonInactiveForegroundColor = Colors.Gray;
52 | if (localSettings.Values["directConnection"] == null)
53 | localSettings.Values["directConnection"] = false;
54 | directConnetion = (bool)localSettings.Values["directConnection"];
55 | chkExperimental.IsChecked = directConnetion;
56 | var refreshTokenCredential = GetCredentialFromLocker(refreshTokenResource);
57 | var passwordCredential = GetCredentialFromLocker(passwordResource);
58 | if (passwordCredential != null)
59 | {
60 | passwordCredential.RetrievePassword();
61 | username = passwordCredential.UserName;
62 | password = passwordCredential.Password;
63 | if (refreshTokenCredential != null)
64 | {
65 | refreshTokenCredential.RetrievePassword();
66 | refreshToken = refreshTokenCredential.Password;
67 | useToken = true;
68 | }
69 | else useToken = false;
70 | Login();
71 | }
72 | }
73 |
74 | private async void BtnReg_Click(object sender, RoutedEventArgs e) =>
75 | await Launcher.LaunchUriAsync(new
76 | Uri(@"https://accounts.pixiv.net/signup?lang=zh&source=pc&view_type=page&ref=wwwtop_accounts_index"));
77 |
78 | private void BtnLogin_Click(object sender, RoutedEventArgs e)
79 | {
80 | username = txtUserName.Text;
81 | password = txtPassword.Password;
82 | if (username == "") txtUserName.Focus(FocusState.Programmatic);
83 | else if (password == "") txtPassword.Focus(FocusState.Programmatic);
84 | else
85 | {
86 | useToken = false;
87 | Login();
88 | }
89 | }
90 |
91 | private async void Login()
92 | {
93 | //启用实验性功能
94 | directConnetion = chkExperimental.IsChecked.Value;
95 | GlobalBaseAPI.ExperimentalConnection = directConnetion;
96 | //保存设置
97 | localSettings.Values["directConnection"] = directConnetion;
98 | stkTxts.Visibility = Visibility.Collapsed;
99 | stkBtns.Visibility = Visibility.Collapsed;
100 | btnTrouble.Visibility = Visibility.Collapsed;
101 | ringProgress.IsActive = true;
102 | grdLoading.Visibility = Visibility.Visible;
103 | bool success;
104 | PixivCS.Objects.AuthResult res = null;
105 | //异步执行登录
106 | try
107 | {
108 | if (useToken)
109 | res = await GlobalBaseAPI.AuthAsync(refreshToken);
110 | else
111 | res = await GlobalBaseAPI.AuthAsync(username, password);
112 | success = true;
113 | }
114 | catch
115 | {
116 | success = false;
117 | if (useToken)
118 | {
119 | useToken = false;
120 | try
121 | {
122 | res = await GlobalBaseAPI.AuthAsync(username, password);
123 | success = true;
124 | }
125 | catch
126 | {
127 | success = false;
128 | }
129 | }
130 | }
131 | if (success)
132 | {
133 | //登录成功
134 | //储存凭证
135 | var vault = new PasswordVault();
136 | try
137 | {
138 | vault.Remove(GetCredentialFromLocker(passwordResource));
139 | vault.Remove(GetCredentialFromLocker(refreshTokenResource));
140 | }
141 | catch { }
142 | finally
143 | {
144 | vault.Add(new PasswordCredential(passwordResource, username, password));
145 | vault.Add(new PasswordCredential(refreshTokenResource, username, Data.OverAll.GlobalBaseAPI.RefreshToken));
146 | }
147 | //保存当前的身份信息
148 | currentUser = Data.CurrentUser.FromObject(res.Response.User);
149 | //如果取消了登录,则避免跳转到主页面
150 | if (isCancelled) resetView();
151 | else Frame.Navigate(typeof(MainPage),null, App.FromRightTransitionInfo);
152 | }
153 | else btnTrouble.Visibility = Visibility.Visible;
154 | }
155 |
156 | private async void BtnTrouble_Click(object sender, RoutedEventArgs e)
157 | {
158 | await Launcher.LaunchUriAsync(new
159 | Uri(@"https://github.com/tobiichiamane/pixivfs-uwp/blob/master/TroubleShoot.md"));
160 | resetView();
161 | }
162 |
163 | private void resetView()
164 | {
165 | isCancelled = false;
166 | stkTxts.Visibility = Visibility.Visible;
167 | stkBtns.Visibility = Visibility.Visible;
168 | ringProgress.IsActive = false;
169 | grdLoading.Visibility = Visibility.Collapsed;
170 | txtUserName.Text = username;
171 | txtPassword.Password = password;
172 | txtPassword.Focus(FocusState.Programmatic);
173 | txtPassword.SelectAll();
174 | }
175 |
176 | private async void Button_Click(object sender, RoutedEventArgs e)
177 | {
178 | await Launcher.LaunchUriAsync(new
179 | Uri(@"https://www.pixiv.net/member_illust.php?mode=medium&illust_id=31251762"));
180 | }
181 |
182 | private async void btnReport_Click(object sender, RoutedEventArgs e)
183 | {
184 | //阻止跳转到主页面
185 | isCancelled = true;
186 | //在新窗口中打开发送反馈的窗口
187 | await ShowNewWindow(typeof(ReportIssuePage), null);
188 | }
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/PixivFSUWP/MainPage.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
15 |
16 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
43 |
44 |
45 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
61 |
62 |
63 |
65 |
66 |
67 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/PixivFSUWP/Package.appxmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
13 |
14 |
15 |
16 |
17 | Pixiv UWP
18 | Testers
19 | Assets\StoreLogo.png
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
34 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | Assets/StoreLogo.png
51 | Pixiv UWP Uri
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/PixivFSUWP/PixivFSUWP_TemporaryKey.pfx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sovetskyfish/pixivfs-uwp/c3e1b8d8cd4eb0f1762c586622d2b21c5103a45e/PixivFSUWP/PixivFSUWP_TemporaryKey.pfx
--------------------------------------------------------------------------------
/PixivFSUWP/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("PixivFSUWP")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("PixivFSUWP")]
13 | [assembly: AssemblyCopyright("Copyright © 2019")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 程序集的版本信息由下列四个值组成:
18 | //
19 | // 主版本
20 | // 次版本
21 | // 生成号
22 | // 修订号
23 | //
24 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
25 | //通过使用 "*",如下所示:
26 | // [assembly: AssemblyVersion("1.0.*")]
27 | [assembly: AssemblyVersion("1.0.0.0")]
28 | [assembly: AssemblyFileVersion("1.0.0.0")]
29 | [assembly: ComVisible(false)]
--------------------------------------------------------------------------------
/PixivFSUWP/Properties/Default.rd.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/PixivFSUWP/ReportIssuePage.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | Report an issue/报告问题
20 | You are going to report an issue. We've collected some details.
21 | 您正准备汇报一个问题,我们收集了一些细节。
22 |
23 |
25 |
26 |
27 | Copy all/全部复制
28 |
29 | Don't worry. The information you just copied does not contain any private data.
30 | 不要担心,您刚刚所复制的信息不会携带您的任何隐私数据。
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/PixivFSUWP/ReportIssuePage.xaml.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Toolkit.Uwp.Helpers;
2 | using System;
3 | using Windows.ApplicationModel;
4 | using Windows.ApplicationModel.Core;
5 | using Windows.ApplicationModel.DataTransfer;
6 | using Windows.System;
7 | using Windows.UI.Popups;
8 | using Windows.UI.ViewManagement;
9 | using Windows.UI.Xaml;
10 | using Windows.UI.Xaml.Controls;
11 |
12 | // https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“空白页”项模板
13 |
14 | namespace PixivFSUWP
15 | {
16 | ///
17 | /// 可用于自身或导航至 Frame 内部的空白页。
18 | ///
19 | public sealed partial class ReportIssuePage : Page
20 | {
21 | public ReportIssuePage()
22 | {
23 | this.InitializeComponent();
24 |
25 | CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true;
26 | var view = ApplicationView.GetForCurrentView();
27 | view.Title = "Report an issue/问题反馈";
28 |
29 | txtDetails.Text += "General:\n";
30 | txtDetails.Text += string.Format("OS version: build {0}\n", SystemInformation.OperatingSystemVersion.Build);
31 | txtDetails.Text += string.Format("App version: {0}.{1}.{2} {3}\n",
32 | Package.Current.Id.Version.Major,
33 | Package.Current.Id.Version.Minor,
34 | Package.Current.Id.Version.Build,
35 | Package.Current.Id.Architecture);
36 | txtDetails.Text += string.Format("Package ID: {0}\n\n", Package.Current.Id.Name);
37 | Windows.Storage.ApplicationDataContainer localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
38 | if (localSettings.Values["isCrashed"] != null &&
39 | (bool)localSettings.Values["isCrashed"] == true &&
40 | localSettings.Values["exception"] != null)
41 | {
42 | localSettings.Values.Remove("isCrashed");
43 | var lastExeption = (string)localSettings.Values["exception"];
44 | txtDetails.Text += "Exception:\n";
45 | txtDetails.Text += lastExeption;
46 | }
47 | }
48 |
49 | private async void BtnCopy_Click(object sender, RoutedEventArgs e)
50 | {
51 | DataPackage dataPackage = new DataPackage();
52 | dataPackage.RequestedOperation = DataPackageOperation.Copy;
53 | dataPackage.SetText(txtDetails.Text);
54 | Clipboard.SetContent(dataPackage);
55 | MessageDialog dialog = new MessageDialog("Valuable information has been copied to clipboard./有价值的信息已经被复制到剪贴板。", "Copied/已复制");
56 | await dialog.ShowAsync();
57 | }
58 |
59 | private async void BtnGitHub_Click(object sender, RoutedEventArgs e)
60 | {
61 | await Launcher.LaunchUriAsync(new
62 | Uri(@"https://github.com/tobiichiamane/pixivfs-uwp/issues/new/choose"));
63 | }
64 |
65 | private async void BtnEmail_Click(object sender, RoutedEventArgs e)
66 | {
67 | await Launcher.LaunchUriAsync(new
68 | Uri(@"mailto:tobiichiamane@outlook.jp"));
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/PixivFSUWP/SettingsPage.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | Pixiv ID:
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
102 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
123 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
141 |
142 |
144 |
146 |
147 |
148 |
149 |
150 |
--------------------------------------------------------------------------------
/PixivFSUWP/SettingsPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using PixivFSUWP.Interfaces;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using Windows.ApplicationModel;
7 | using Windows.Security.Credentials;
8 | using Windows.System;
9 | using Windows.UI.Xaml;
10 | using Windows.UI.Xaml.Controls;
11 | using Windows.UI.Xaml.Navigation;
12 | using static PixivFSUWP.Data.OverAll;
13 | using Windows.Storage;
14 |
15 | // https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“空白页”项模板
16 |
17 | namespace PixivFSUWP
18 | {
19 | ///
20 | /// 可用于自身或导航至 Frame 内部的空白页。
21 | ///
22 | public sealed partial class SettingsPage : Page, IGoBackFlag
23 | {
24 | public SettingsPage()
25 | {
26 | this.InitializeComponent();
27 | _ = loadContentsAsync();
28 | }
29 |
30 | private bool _backflag { get; set; } = false;
31 |
32 | public void SetBackFlag(bool value)
33 | {
34 | _backflag = value;
35 | }
36 |
37 | protected override void OnNavigatedTo(NavigationEventArgs e)
38 | {
39 | base.OnNavigatedTo(e);
40 | TheMainPage?.SelectNavPlaceholder(GetResourceString("SettingsPagePlain"));
41 | }
42 |
43 | protected override void OnNavigatedFrom(NavigationEventArgs e)
44 | {
45 | base.OnNavigatedFrom(e);
46 | if (!_backflag)
47 | {
48 | Data.Backstack.Default.Push(typeof(SettingsPage), null);
49 | TheMainPage?.UpdateNavButtonState();
50 | }
51 | }
52 |
53 | async Task loadContentsAsync()
54 | {
55 | var imgTask = LoadImageAsync(currentUser.Avatar170);
56 | txtVersion.Text = GetResourceString("ReleasedVersion") + string.Format("{0} version-{1}.{2}.{3} {4}",
57 | Package.Current.DisplayName,
58 | Package.Current.Id.Version.Major,
59 | Package.Current.Id.Version.Minor,
60 | Package.Current.Id.Version.Build,
61 | Package.Current.Id.Architecture);
62 | txtPkgName.Text = GetResourceString("ReleasedID") + string.Format("{0}", Package.Current.Id.Name);
63 | txtInsDate.Text = GetResourceString("ReleasedTime") + string.Format("{0}", Package.Current.InstalledDate.ToLocalTime().DateTime);
64 | txtID.Text = currentUser.ID.ToString();
65 | txtName.Text = currentUser.Username;
66 | txtAccount.Text = "@" + currentUser.UserAccount;
67 | txtEmail.Text = currentUser.Email;
68 | //硬编码主要开发者信息
69 | List mainDevs = new List();
70 | mainDevs.Add(new ViewModels.ContributorViewModel()
71 | {
72 | Account = "@tobiichiamane",
73 | DisplayName = "Communist Fish",
74 | AvatarUrl = "https://avatars2.githubusercontent.com/u/14824064?v=4&s=45",
75 | ProfileUrl = "https://github.com/tobiichiamane",
76 | Contributions = new List()
77 | {
78 | Data.Contribution.bug,
79 | Data.Contribution.code,
80 | Data.Contribution.doc,
81 | Data.Contribution.idea,
82 | Data.Contribution.translation
83 | }
84 | });
85 | lstMainDev.ItemsSource = mainDevs;
86 | //加载贡献者信息
87 | _ = loadContributors();
88 | //TODO: 考虑设置项不存在的情况
89 | //ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings;
90 | //tbSauceNAO.Text = localSettings.Values["SauceNAOAPI"] as string;//读取设置项
91 | //tbImgur.Text = localSettings.Values["ImgurAPI"] as string;
92 | // 获取储存的颜色主题信息
93 | switch (ApplicationData.Current.LocalSettings.Values["ColorTheme"])
94 | {
95 | case false:
96 | cboxColorTheme.SelectedIndex = 0;
97 | break;
98 | case true:
99 | cboxColorTheme.SelectedIndex = 1;
100 | break;
101 | default:
102 | cboxColorTheme.SelectedIndex = 2;
103 | break;
104 | }
105 |
106 | _ = calculateCacheSize();
107 | //等待头像加载完毕
108 | imgAvatar.ImageSource = await imgTask;
109 | }
110 |
111 | async Task loadContributors()
112 | {
113 | progressLoadingContributors.Visibility = Visibility.Visible;
114 | progressLoadingContributors.IsActive = true;
115 | var res = await Data.ContributorsHelper.GetContributorsAsync();
116 | if (res == null)
117 | {
118 | progressLoadingContributors.Visibility = Visibility.Collapsed;
119 | progressLoadingContributors.IsActive = false;
120 | txtContributors.Text = GetResourceString("ContributorsReadingErrorPlain");
121 | return;
122 | }
123 | var enumerable = from item in res select ViewModels.ContributorViewModel.FromItem(item);
124 | lstContributors.ItemsSource = enumerable.ToList();
125 | progressLoadingContributors.Visibility = Visibility.Collapsed;
126 | progressLoadingContributors.IsActive = false;
127 | lstContributors.Visibility = Visibility.Visible;
128 | }
129 |
130 | async Task calculateCacheSize()
131 | {
132 | //计算缓存大小
133 | var cacheSize = await Data.CacheManager.GetCacheSizeAsync();
134 | decimal sizeInMB = new decimal(cacheSize) / new decimal(1048576);
135 | txtCacheSize.Text = decimal.Round(sizeInMB, 2).ToString() + "MB";
136 | }
137 |
138 | private void BtnLogout_Click(object sender, RoutedEventArgs e)
139 | {
140 | var vault = new PasswordVault();
141 | try
142 | {
143 | vault.Remove(GetCredentialFromLocker(passwordResource));
144 | vault.Remove(GetCredentialFromLocker(refreshTokenResource));
145 | }
146 | catch { }
147 | finally
148 | {
149 | TheMainPage.Frame.Navigate(typeof(LoginPage), null, App.FromRightTransitionInfo);
150 | }
151 | }
152 |
153 | private async void BtnGithub_Click(object sender, RoutedEventArgs e)
154 | {
155 | await Launcher.LaunchUriAsync(new
156 | Uri(@"https://github.com/sovetskyfish/pixivfs-uwp"));
157 | }
158 |
159 | private void API_TextChanged(object sender, TextChangedEventArgs e)
160 | {
161 | ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings;
162 | localSettings.Values["SauceNAOAPI"] = tbSauceNAO.Text;
163 | localSettings.Values["ImgurAPI"] = tbImgur.Text;
164 | }
165 |
166 | private async void btnClearCache_Click(object sender, RoutedEventArgs e)
167 | {
168 | txtCacheSize.Text = GetResourceString("Recalculating");
169 | await Data.CacheManager.ClearCacheAsync();
170 | await calculateCacheSize();
171 | }
172 |
173 | private async void btnDelInvalid_Click(object sender, RoutedEventArgs e)
174 | {
175 | txtCacheSize.Text = GetResourceString("Recalculating");
176 | await Data.CacheManager.ClearTempFilesAsync();
177 | await calculateCacheSize();
178 | }
179 |
180 | private async void lstMainDev_ItemClick(object sender, ItemClickEventArgs e)
181 | {
182 | var item = e.ClickedItem as ViewModels.ContributorViewModel;
183 | await Launcher.LaunchUriAsync(new Uri(item.ProfileUrl));
184 | }
185 |
186 | private async void btnQQGroup_Click(object sender, RoutedEventArgs e)
187 | {
188 | //腾讯的一键加群
189 | await Launcher.LaunchUriAsync(new
190 | Uri(@"https://shang.qq.com/wpa/qunwpa?idkey=d6ba54103ced0e2d7c5bbf6422e4f9f6fa4849c91d4521fe9a1beec72626bbb6"));
191 | }
192 |
193 | private void ComboBox_DropDownClosed(object sender, object e)
194 | {
195 | if(sender is ComboBox cb)
196 | {
197 | // 保存颜色主题信息
198 | switch (cb.SelectedIndex)
199 | {
200 | case 2:
201 | ApplicationData.Current.LocalSettings.Values["ColorTheme"] = null;
202 | break;
203 | case 0:
204 | ApplicationData.Current.LocalSettings.Values["ColorTheme"] = false;
205 | break;
206 | case 1:
207 | ApplicationData.Current.LocalSettings.Values["ColorTheme"] = true;
208 | break;
209 | }
210 | _ = TheMainPage?.ShowTip(GetResourceString("RestartApplyColorTheme"));
211 | }
212 | }
213 | }
214 | }
215 |
--------------------------------------------------------------------------------
/PixivFSUWP/Themes/Dark.xaml:
--------------------------------------------------------------------------------
1 |
5 | /Assets/PixivHeader_L.png
6 | /Assets/PixivText_L.png
7 | 0.7
8 |
9 |
--------------------------------------------------------------------------------
/PixivFSUWP/Themes/Light.xaml:
--------------------------------------------------------------------------------
1 |
5 | /Assets/PixivHeader.png
6 | /Assets/PixivText.png
7 | 0.5
8 |
9 |
--------------------------------------------------------------------------------
/PixivFSUWP/ViewModels/CommentViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.ComponentModel;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using Windows.UI.Xaml.Media.Imaging;
9 |
10 | namespace PixivFSUWP.ViewModels
11 | {
12 | public class CommentViewModel : INotifyPropertyChanged
13 | {
14 | public int ID { get; set; }
15 | public string Comment { get; set; }
16 | public string UserName { get; set; }
17 | public string UserAccount { get; set; }
18 | private string _dateTime { get; set; }
19 | public string AvatarUrl { get; set; }
20 | public BitmapImage Avatar { get; set; }
21 | public int ParentID { get; set; }
22 | public ObservableCollection ChildrenComments { get; set; } = null;
23 |
24 | public string DateTime
25 | {
26 | get => DateTimeOffset.Parse(_dateTime).LocalDateTime.ToString();
27 | }
28 |
29 | public event PropertyChangedEventHandler PropertyChanged;
30 |
31 | public async Task LoadAvatarAsync()
32 | {
33 | Avatar = await Data.OverAll.LoadImageAsync(AvatarUrl);
34 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Avatar"));
35 | }
36 |
37 | public static CommentViewModel FromItem(Data.IllustCommentItem Item)
38 | {
39 | return new CommentViewModel()
40 | {
41 | ID = Item.ID,
42 | Comment = Item.Comment,
43 | UserName = Item.UserName,
44 | UserAccount = "@" + Item.UserAccount,
45 | _dateTime = Item.DateTime,
46 | AvatarUrl = Item.AvatarUrl,
47 | ParentID = Item.ParentCommentID
48 | };
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/PixivFSUWP/ViewModels/ContributorViewModel.cs:
--------------------------------------------------------------------------------
1 | using PixivFSUWP.Data;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace PixivFSUWP.ViewModels
9 | {
10 | public class ContributorViewModel
11 | {
12 | public string AvatarUrl { get; set; }
13 | public string DisplayName { get; set; }
14 | public string Account { get; set; }
15 | public string ProfileUrl { get; set; }
16 | public List Contributions { get; set; }
17 |
18 | public static ContributorViewModel FromItem(Contributor Item)
19 | {
20 | return new ContributorViewModel()
21 | {
22 | AvatarUrl = Item.AvatarUrl + "&s=45",
23 | DisplayName = Item.DisplayName,
24 | Account = "@" + Item.Account,
25 | ProfileUrl = Item.ProfileUrl,
26 | Contributions = Item.Contributions
27 | };
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/PixivFSUWP/ViewModels/ImageItemViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.UI.Xaml.Media.Imaging;
7 |
8 | namespace PixivFSUWP.ViewModels
9 | {
10 | public class ImageItemViewModel
11 | {
12 | public WriteableBitmap ImageSource { get; set; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/PixivFSUWP/ViewModels/TagViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace PixivFSUWP.ViewModels
8 | {
9 | public class TagViewModel
10 | {
11 | public string Tag { get; set; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/PixivFSUWP/ViewModels/WaterfallItemViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using PixivFSUWP.Data;
7 | using Windows.UI.Xaml.Media.Imaging;
8 | using System.IO;
9 | using System.ComponentModel;
10 |
11 | namespace PixivFSUWP.ViewModels
12 | {
13 | public class WaterfallItemViewModel : INotifyPropertyChanged
14 | {
15 | public int ItemId { get; private set; }
16 | public string Title { get; set; }
17 | public string Author { get; set; }
18 | public string ImageUri { get; set; }
19 | public int Stars { get; set; }
20 | public int Pages { get; set; }
21 | public bool IsBookmarked { get; set; }
22 | public BitmapImage ImageSource { get; set; }
23 | public int Width { get; set; }
24 | public int Height { get; set; }
25 |
26 | public event PropertyChangedEventHandler PropertyChanged;
27 |
28 | public async Task LoadImageAsync()
29 | {
30 | ImageSource = await Data.OverAll.LoadImageAsync(ImageUri);
31 | }
32 |
33 | public string StarsString
34 | {
35 | get
36 | {
37 | return "★" + Stars.ToString();
38 | }
39 | }
40 |
41 | public static WaterfallItemViewModel FromItem(WaterfallItem Item)
42 | => new WaterfallItemViewModel()
43 | {
44 | ItemId = Item.Id,
45 | Title = Item.Title,
46 | Author = Item.Author,
47 | ImageUri = Item.ImageUri,
48 | IsBookmarked = Item.IsBookmarked,
49 | Stars = Item.Stars,
50 | Pages = Item.Pages,
51 | Width = Item.Width,
52 | Height = Item.Height
53 | };
54 |
55 | public void NotifyChange(string PropertyName)
56 | {
57 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/PixivFSUWP/WaterfallPage.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | **This project is deprecated due to my ever worse health condition (and those hard-to-maintenance code I wrote when drunk😂).**
2 | **Use [Pixeval](https://github.com/Rinacm/Pixeval) if you want a more comfortable experience, or wait for Win32/UWP support of [PixEz-Flutter](https://github.com/Notsfsssf/pixez-flutter). These projects are developed by two of my friends and are way more usable than Pixiv UWP.**
3 |
4 | # Pixiv UWP 2 [](https://dev.azure.com/tobiichiamane/pixivfs-uwp/_build?definitionId=1)
5 |
6 | [
](https://www.microsoft.com/store/apps/9PM8K64J71PL?cid=storebadge&ocid=badge)
7 |
8 | 已发布至商店。所有的依赖都是Nuget包,所以除了安装有[Multilingual App Toolkit](http://aka.ms/matinstall)的VS2019和Windows SDK 17763以外你不需要任何特殊的环境来编译代码。你也可以从Azure Pipelines获取Artifact,或者从Release页面获取包。
9 |
10 | Almost useable. All dependencies are available on Nuget, so you don't need any special environment to compile except Visual Studio 2019 with [Multilingual App Toolkit](http://aka.ms/matinstall) installed and Windows SDK 17763. Instead, you can get the compiled artifact from Azure Pipelines, or get it from the releases page.
11 |
12 | 由于.NET Native[暂不完整支持F#](https://github.com/dotnet/corert/issues/6055),本应用暂时使用[pixivcs](https://github.com/tobiichiamane/pixivcs)而不是[pixivfs](https://github.com/tobiichiamane/pixivfs)编写。
13 |
14 | Because .NET Native [hasn't fully supported F# yet](https://github.com/dotnet/corert/issues/6055), this project is based on [pixivcs](https://github.com/tobiichiamane/pixivcs) rather than [pixivfs](https://github.com/tobiichiamane/pixivfs).
15 |
16 | 如果您也使用安卓设备,那么[@Notsfsssf](https://github.com/Notsfsssf)开发的[Pix-EzViewer](https://github.com/Notsfsssf/Pix-EzViewer)会是不错的选择。
17 |
18 | If you also use Android devices, [Pix-EzViewer](https://github.com/Notsfsssf/Pix-EzViewer) developed by [@Notsfsssf](https://github.com/Notsfsssf) will be a great alternative to the official app.
19 |
20 | 如果您正使用版本低于Windows 10 Version 17134或更旧的操作系统(包括Windows 8.1、Windows 8和Windows 7在内),或者单纯希望获得非UWP的桌面体验,则[@Rinacm](https://github.com/Rinacm)开发的[Pixeval](https://github.com/Rinacm/Pixeval)将会给予您优秀的使用体验。
21 |
22 | If you are running Windows 10 version 17134 or older (including Windows 8, Windows 8.1 and Windows 7), or you just want a non-UWP desktop experience, [Pixeval](https://github.com/Rinacm/Pixeval) developed by [@Rinacm](https://github.com/Rinacm) will be the perfect choice.
23 |
24 | # 翻译/Translation
25 |
26 | 本应用急需翻译人员。参照[如何翻译](https://github.com/tobiichiamane/pixivfs-uwp/blob/master/Translate.md)。
27 |
28 | Any help to translate this app will be appreciated. Please read [*How to translate*](https://github.com/tobiichiamane/pixivfs-uwp/blob/master/Translate.md).
29 |
30 | # 参与者/Contributors ✨
31 |
32 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
33 |
34 |
35 |
36 |
37 |
63 |
64 |
65 |
66 |
67 |
68 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
69 |
70 | # Special thanks
71 |
72 | Thanks [JetBrains](https://www.jetbrains.com/?from=pixivuwp) for kindly supporting this project.
73 |
74 | # Buy me a coffee?
75 |
76 | [](https://ko-fi.com/P5P8WD5C)
77 |
--------------------------------------------------------------------------------
/Translate.md:
--------------------------------------------------------------------------------
1 | # 如何翻译/How to translate
2 |
3 | ## 使用Visual Studio/Using Visual Studio
4 |
5 | **请确保您的Visual Studio安装有[Multilingual App Toolkit](http://aka.ms/matinstall)。**
6 |
7 | **Please make sure you have [Multilingual App Toolkit](http://aka.ms/matinstall) installed for your Visual Studio.**
8 |
9 | 使用Visual Studio加载解决方案,在解决方案资源管理器中右击项目PixivFSUWP,选择“Multilingual App Toolkit”->“添加翻译语言...”,忽略可能产生“翻译提供程序管理器问题”,选择并添加您要翻译的语言;在MultilingualResources目录下,翻译新添加的语言之xlf文件。
10 |
11 | Load the solution with Visual Studio, then right click the project named PixivFSUWP in Solution Explorer. Click *Multilingual App Toolkit* -> *Add translation languages...* and select the language you want to add. Translate the newly generated xlf file of your language.
12 |
13 | ## 不熟悉Visual Studio?/Not familiar with Visual Studio?
14 |
15 | 请使用[英文资源文件](https://github.com/tobiichiamane/pixivfs-uwp/blob/master/PixivFSUWP/Strings/en/Resources.resw)为蓝本,翻译出其它的语言。翻译完毕后,请将文件发送至[开发者的邮箱](mailto:tobiichiamane@outlook.jp)并附上英文说明。
16 |
17 | Please use [Resources.resw](https://github.com/tobiichiamane/pixivfs-uwp/blob/master/PixivFSUWP/Strings/en/Resources.resw) as your blueprint. Send the translated file, along with some descriptions, to [my email](mailto:tobiichiamane@outlook.jp).
--------------------------------------------------------------------------------
/TroubleShoot.md:
--------------------------------------------------------------------------------
1 | # 解决登录问题的一般步骤
2 |
3 | ## 检查您的应用版本
4 |
5 | 任何早于[v2.5.4](https://github.com/tobiichiamane/pixivfs-uwp/tree/v2.5.4)的版本都有可能出现无法使用用户名和密码登录的情况,这是Pixiv升级了其API所造成的。请更新应用至v2.5.4及以后版本来获得正常体验。
6 |
7 | ## 中国大陆用户特别注意
8 |
9 | Pixiv及其相关服务在中国大陆处于被封锁状态,若希望使用PixivUWP,则必须使用稳定的代理工具;对于部分代理工具(如Shadowsocks等)则需要解除UWP应用的本地回环限制。
10 |
11 | **!实验性功能!** 在[版本2.2.1](https://github.com/tobiichiamane/pixivfs-uwp/tree/v2.2.1)之后,你可以在登录时勾选“直连”功能以期绕过中国大陆的封锁。对于某些地区,此功能未必有效;对于此功能有效的地区,连接速度可能会不理想。
12 |
13 | ### 解除UWP应用本地回环限制
14 |
15 | **使用命令提示符(而非PowerShell)**
16 |
17 | - 若您的应用来自于GitHub或Azure DevOps:
18 | ```cmd
19 | checknetisolation loopbackexempt -a -n=31db69de-89d1-4fa9-9878-fcd942f090ca_5v6yvh15ag700
20 | ```
21 |
22 | - 若您的应用来自于商店:
23 | ```cmd
24 | checknetisolation loopbackexempt -a -n=18416PixeezPlusProject.PixivUWP_fsr1r9g7nfjfw
25 | ```
26 |
27 | **使用[Fiddler](https://www.telerik.com/fiddler)**
28 |
29 | - 下载并安装Fiddler
30 | - 启动Fiddler,并点击工具栏上第一个按钮“WinConfig”
31 | - 勾选PixivUWP并保存更改
32 |
33 | ### 确保代理工具正在代理PixivUWP正在使用的域名
34 |
35 | PixivUWP使用下列域名完成应用功能:
36 |
37 | - app-api.pixiv.net/*
38 | - public-api.secure.pixiv.net/*
39 | - oauth.secure.pixiv.net/*
40 | - public-api.pixiv.net/*
41 |
42 | Pixiv的图片由以下域名提供:
43 |
44 | - i.pximg.net/*
45 |
46 | 请确保将这些域名加入你的代理列表中。
47 |
48 | ## 确保你有正常的网络连接
49 |
50 | 能正常访问互联网不代表着您能正常访问Pixiv及其相关服务。请确保您的网络能正常连接至Pixiv。
51 |
52 | ## 检查你的用户名和密码
53 |
54 | 错误的用户名和密码将不能登入PixivUWP。PixivUWP目前不提供未登录状态的任何功能。
55 |
--------------------------------------------------------------------------------
/UpdataLog.md:
--------------------------------------------------------------------------------
1 | ======================
2 | # 缺少的资源
3 | >| 控件UID | 控件类型 | 中文字符串 | √ |
4 | >|:-:|:-:|:-:|:-:|
5 | >| QuickLS | MenuFlyoutItem | 一键二连 | Text
6 | >| SauceNaoAPI | TextBlock | SauceNAO API | Text
7 | >| ImgurAPI | TextBlock | Imgur API | Text
8 | >| ImageDir | TextBlock | 图像保存目录 | Text
9 | >| SearchMore | TextBlock | 更多搜索功能 | Text
10 | >| BtnSauceNAO | Button | 以图搜图 | Content
11 | >| GoPixivID | AutoSuggestBox | Pixiv ID | PlaceholderText
12 | >| GoToPixivID | TextBlock | 跳到ID | Text
13 | >| | | |
14 | >| | | |
15 | >| | | |
16 | # 引用
17 | * [SauceNao-Windows](https://github.com/RoxasShadow/SauceNao-Windows)
18 | ╞ ┕ ╘ ├
19 | # 更新
20 | > |符号|含义|
21 | > |:-:|:-:|
22 | > +|添加
23 | > -|移除
24 | > *|优化
25 | > !|修复
26 |
27 | 以下正文
28 | >| | 主要内容 | 补充 |
29 | >|:-:|:-:|:-|
30 | >+| 一键二连|创建一个合并了快速收藏和快速保存功能的按钮
31 | >+| 以图搜图|通过使用用户自定的API搜图
32 | >+| 快速保存|将文件快速保存至设定的目录
33 | >*| 拓展名识别|将自动识别图片的拓展名
34 | >*| 以图搜图优化 |完善以图搜图
35 | >+| PixivID搜图 |可以通过直接输入图片ID搜图
36 | >*| 代码优化 | 创建SauceNAO搜索页
37 | >|| ├ | 创建Go To Pixiv ID页
38 | >|| ┕| 将 以图搜图 ID搜图 合并至 搜索
39 | >!|重要修复|停用会导致异常的Go To Pixiv ID页
40 | >*|资源添加|开始尝试添加本地化字符串
41 | >-|删除无用页|将会导致异常的Go To Pixiv ID页移除
42 | >*|优化ID搜图|为ID搜图设置图标
43 | >|||!!断网无调试云写代码警告!!
44 | >*|資源添加|使用MAT工具添加字符串
45 | >|||我云寫代碼成功了!可把我牛逼坏了(插会腰)
46 | >!|修复字符串|刚刚好像没推送出去..重推
47 | >-|删除SauceNAO API|将SauceNAO相关API移至项目PixivCS
48 | >!|修订|根据PixivCS修改代码
49 | >*|快速保存|将文件快速保存至设定的目录
50 | >!|更新PixivCS包|更新项目引用的PixivCS的nuget包
--------------------------------------------------------------------------------
/azure-pipelines.yml:
--------------------------------------------------------------------------------
1 | # Universal Windows Platform
2 | # Build a Universal Windows Platform project using Visual Studio.
3 | # Add steps that test and distribute an app, save build artifacts, and more:
4 | # https://aka.ms/yaml
5 |
6 | trigger:
7 | - master
8 |
9 | pool:
10 | vmImage: 'windows-2019'
11 |
12 | variables:
13 | solution: '**/*.sln'
14 | buildPlatform: 'x86|x64|ARM'
15 | buildConfiguration: 'Release'
16 | appxPackageDir: '$(build.artifactStagingDirectory)\AppxPackages\\'
17 |
18 | steps:
19 | - task: NuGetToolInstaller@0
20 |
21 | - task: NuGetCommand@2
22 | inputs:
23 | restoreSolution: '$(solution)'
24 |
25 | - task: VSBuild@1
26 | inputs:
27 | platform: 'x86'
28 | solution: '$(solution)'
29 | configuration: '$(buildConfiguration)'
30 | msbuildArgs: '/p:AppxBundlePlatforms="$(buildPlatform)" /p:AppxPackageDir="$(appxPackageDir)" /p:AppxBundle=Always /p:UapAppxPackageBuildMode=Sideload'
31 |
32 |
33 | - task: CopyFiles@2
34 | displayName: 'Copy Files to: $(build.artifactstagingdirectory)'
35 | inputs:
36 | SourceFolder: '$(system.defaultworkingdirectory)'
37 | Contents: '**\bin\$(BuildConfiguration)\**'
38 | TargetFolder: '$(build.artifactstagingdirectory)'
39 |
40 | - task: ArchiveFiles@2
41 | inputs:
42 | rootFolderOrFile: '$(build.artifactstagingdirectory)'
43 | includeRootFolder: false
44 | archiveType: 'zip'
45 | archiveFile: '$(build.artifactstagingdirectory)/Package.zip'
46 | replaceExistingArchive: true
47 |
48 | - task: PublishBuildArtifacts@1
49 | displayName: 'Publish Artifact: Package'
50 | inputs:
51 | artifactName: 'Package'
52 | PathtoPublish: '$(build.artifactstagingdirectory)/Package.zip'
53 |
54 | - task: GitHubRelease@0
55 | displayName: 'Release Artifact to Github'
56 | inputs:
57 | gitHubConnection: 'releasetogithub'
58 | isPreRelease: true
59 | assets: '$(build.artifactstagingdirectory)/Package.zip'
60 | assetUploadMode: 'delete'
--------------------------------------------------------------------------------