├── .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 | 3 | 5 | 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 | 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 | 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/_apis/build/status/tobiichiamane.pixivfs-uwp?branchName=master)](https://dev.azure.com/tobiichiamane/pixivfs-uwp/_build?definitionId=1) 5 | 6 | [English badge](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 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |

chenxuuu

📖

逢坂桜

🌍

TuMIer

🐛

Raze Soldier

🐛

Funny-ppt

🐛

dsyo2008

🤔

Henry He

🐛 💻

舰队的偶像-岛风酱!

💻

handsome-yaokun

🐛

Baka632

🐛

pccanales

🐛

SLK-xlw

🐛

Star sea

🐛

FengBuJue

💻

hokori

🐛

Shary0x62

💻

ProJend

💻

いんしさくら

🌍
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 | [![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](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' --------------------------------------------------------------------------------