From c0ff0ca628991200b01831d4af2bfbf3f3a6703f Mon Sep 17 00:00:00 2001 From: Brycen G Date: Mon, 7 Jul 2025 23:04:22 -0400 Subject: [PATCH 01/31] refactor(Core): merge ScreenCapture directory into SharpCapture --- SnapX.Core/OSX.props | 5 +- .../Animations/BaseAnimation.cs | 0 .../Animations/ColorBlinkAnimation.cs | 0 .../Animations/OpacityAnimation.cs | 0 .../Animations/PointAnimation.cs | 0 .../Animations/RectangleAnimation.cs | 0 .../Animations/TextAnimation.cs | 0 .../Helpers/InputManager.cs | 0 .../Helpers/LocationInfo.cs | 0 .../Helpers/SimpleWindowInfo.cs | 0 .../Helpers/SnapSize.cs | 0 .../Helpers/WindowsList.cs | 0 .../Rust/Cargo.lock | 0 .../Rust/Cargo.toml | 0 .../Rust/bindings/snapxrust.cs | 0 .../SharpCapture/Rust/bindings/snapxrust.py | 1090 +++++++++++++++++ .../Rust/build.rs | 0 .../Rust/src/lib.rs | 0 .../Rust/src/snapxrust.udl | 0 .../ScreenRecording/FFmpegCaptureDevice.cs | 0 .../ScreenRecording/FFmpegOptions.cs | 0 .../ScreenRecording/HardDiskCache.cs | 0 .../ScreenRecording/ImageCache.cs | 0 .../ScreenRecording/ScreenRecorder.cs | 0 .../ScreenRecording/ScreenRecordingOptions.cs | 0 .../Stickers/BlobEmoji/b1nzyblob.png | Bin .../Stickers/BlobEmoji/b1nzyblob2.png | Bin .../Stickers/BlobEmoji/b4nzyblob.png | Bin .../Stickers/BlobEmoji/blob.png | Bin .../Stickers/BlobEmoji/blob0w0.png | Bin .../Stickers/BlobEmoji/blob3c.png | Bin .../Stickers/BlobEmoji/blob3cevil.png | Bin .../Stickers/BlobEmoji/blobaffection.png | Bin .../Stickers/BlobEmoji/blobamused.png | Bin .../Stickers/BlobEmoji/blobangel.png | Bin .../Stickers/BlobEmoji/blobangery.png | Bin .../Stickers/BlobEmoji/blobangry.png | Bin .../Stickers/BlobEmoji/blobangry2.png | Bin .../Stickers/BlobEmoji/blobangrypuff.png | Bin .../Stickers/BlobEmoji/blobartist.png | Bin .../Stickers/BlobEmoji/blobaviator.png | Bin .../Stickers/BlobEmoji/blobawkward.png | Bin .../Stickers/BlobEmoji/blobaww.png | Bin .../Stickers/BlobEmoji/blobbandage.png | Bin .../Stickers/BlobEmoji/blobbanhammer.png | Bin .../Stickers/BlobEmoji/blobbathtub.png | Bin .../Stickers/BlobEmoji/blobblackcat.png | Bin .../Stickers/BlobEmoji/blobblush.png | Bin .../Stickers/BlobEmoji/blobboost.png | Bin .../Stickers/BlobEmoji/blobbored.png | Bin .../Stickers/BlobEmoji/blobbot.png | Bin .../Stickers/BlobEmoji/blobbowing.png | Bin .../Stickers/BlobEmoji/blobbroken.png | Bin .../Stickers/BlobEmoji/blobcamera.png | Bin .../Stickers/BlobEmoji/blobcat.png | Bin .../Stickers/BlobEmoji/blobcheeky.png | Bin .../Stickers/BlobEmoji/blobcheer.png | Bin .../Stickers/BlobEmoji/blobcheerful.png | Bin .../Stickers/BlobEmoji/blobcheerful2.png | Bin .../Stickers/BlobEmoji/blobclipboard.png | Bin .../Stickers/BlobEmoji/blobcmereyou.png | Bin .../Stickers/BlobEmoji/blobcocoa.png | Bin .../Stickers/BlobEmoji/blobcomfort.png | Bin .../Stickers/BlobEmoji/blobconcerned.png | Bin .../Stickers/BlobEmoji/blobconfounded.png | Bin .../Stickers/BlobEmoji/blobconfused.png | Bin .../Stickers/BlobEmoji/blobcool.png | Bin .../Stickers/BlobEmoji/blobcouncil.png | Bin .../Stickers/BlobEmoji/blobcouple.png | Bin .../Stickers/BlobEmoji/blobcowboy.png | Bin .../Stickers/BlobEmoji/blobcry.png | Bin .../Stickers/BlobEmoji/blobdancer.png | Bin .../Stickers/BlobEmoji/blobdead.png | Bin .../Stickers/BlobEmoji/blobderpy.png | Bin .../Stickers/BlobEmoji/blobderpyhappy.png | Bin .../Stickers/BlobEmoji/blobdetective.png | Bin .../Stickers/BlobEmoji/blobdevil.png | Bin .../Stickers/BlobEmoji/blobdevilsmile.png | Bin .../Stickers/BlobEmoji/blobdisapproval.png | Bin .../Stickers/BlobEmoji/blobdisguise.png | Bin .../Stickers/BlobEmoji/blobdizzy.png | Bin .../Stickers/BlobEmoji/blobdizzy2.png | Bin .../Stickers/BlobEmoji/blobdoctor.png | Bin .../Stickers/BlobEmoji/blobdoubt.png | Bin .../Stickers/BlobEmoji/blobdoubtful.png | Bin .../Stickers/BlobEmoji/blobdrool.png | Bin .../Stickers/BlobEmoji/blobeagle.png | Bin .../Stickers/BlobEmoji/blobembarrassed.png | Bin .../Stickers/BlobEmoji/blobembarrassed2.png | Bin .../Stickers/BlobEmoji/blobenjoy.png | Bin .../Stickers/BlobEmoji/bloberm.png | Bin .../Stickers/BlobEmoji/blobexpressionless.png | Bin .../Stickers/BlobEmoji/blobeyesdown.png | Bin .../Stickers/BlobEmoji/blobeyesup.png | Bin .../Stickers/BlobEmoji/blobfacemask.png | Bin .../Stickers/BlobEmoji/blobfacepalm.png | Bin .../Stickers/BlobEmoji/blobfearful.png | Bin .../Stickers/BlobEmoji/blobfingerguns.png | Bin .../Stickers/BlobEmoji/blobfingerscrossed.png | Bin .../Stickers/BlobEmoji/blobfirefighter.png | Bin .../Stickers/BlobEmoji/blobfistbumpL.png | Bin .../Stickers/BlobEmoji/blobfistbumpR.png | Bin .../Stickers/BlobEmoji/blobflushed.png | Bin .../Stickers/BlobEmoji/blobfreezing.png | Bin .../Stickers/BlobEmoji/blobfrog.png | Bin .../Stickers/BlobEmoji/blobfrown.png | Bin .../Stickers/BlobEmoji/blobfrowning.png | Bin .../Stickers/BlobEmoji/blobfrowningbig.png | Bin .../Stickers/BlobEmoji/blobgamer.png | Bin .../Stickers/BlobEmoji/blobgift.png | Bin .../Stickers/BlobEmoji/blobgiggle.png | Bin .../Stickers/BlobEmoji/blobglare.png | Bin .../Stickers/BlobEmoji/blobglarepolice.png | Bin .../Stickers/BlobEmoji/blobglassesdown.png | Bin .../Stickers/BlobEmoji/blobgo.png | Bin .../Stickers/BlobEmoji/blobgoat.png | Bin .../Stickers/BlobEmoji/blobgoodmorning.png | Bin .../BlobEmoji/blobgoodmorningreverse.png | Bin .../Stickers/BlobEmoji/blobgoodnight.png | Bin .../BlobEmoji/blobgoodnightreverse.png | Bin .../Stickers/BlobEmoji/blobgrimace.png | Bin .../Stickers/BlobEmoji/blobgrin.png | Bin .../Stickers/BlobEmoji/blobgrumpy.png | Bin .../Stickers/BlobEmoji/blobheart.png | Bin .../Stickers/BlobEmoji/blobhearteyes.png | Bin .../Stickers/BlobEmoji/blobhero.png | Bin .../Stickers/BlobEmoji/blobhighfive.png | Bin .../Stickers/BlobEmoji/blobhug.png | Bin .../Stickers/BlobEmoji/blobhug2.png | Bin .../Stickers/BlobEmoji/blobhuh.png | Bin .../Stickers/BlobEmoji/blobhushed.png | Bin .../Stickers/BlobEmoji/blobhyperthink.png | Bin .../Stickers/BlobEmoji/blobhyperthinkfast.png | Bin .../Stickers/BlobEmoji/blobhypesquad.png | Bin .../Stickers/BlobEmoji/blobidea.png | Bin .../Stickers/BlobEmoji/blobimfine.png | Bin .../Stickers/BlobEmoji/blobinlove.png | Bin .../Stickers/BlobEmoji/blobjam.png | Bin .../Stickers/BlobEmoji/blobjoy.png | Bin .../Stickers/BlobEmoji/blobkiss.png | Bin .../Stickers/BlobEmoji/blobkissblush.png | Bin .../Stickers/BlobEmoji/blobkissheart.png | Bin .../Stickers/BlobEmoji/bloblamp.png | Bin .../Stickers/BlobEmoji/bloblul.png | Bin .../Stickers/BlobEmoji/blobmail.png | Bin .../Stickers/BlobEmoji/blobmaracas.png | Bin .../Stickers/BlobEmoji/blobmelt.png | Bin .../Stickers/BlobEmoji/blobmeltblush.png | Bin .../Stickers/BlobEmoji/blobmeltsob.png | Bin .../Stickers/BlobEmoji/blobmeltsoblove.png | Bin .../Stickers/BlobEmoji/blobmindblown.png | Bin .../Stickers/BlobEmoji/blobmlem.png | Bin .../Stickers/BlobEmoji/blobmorning.png | Bin .../Stickers/BlobEmoji/blobmoustache.png | Bin .../Stickers/BlobEmoji/blobnauseated.png | Bin .../Stickers/BlobEmoji/blobnerd.png | Bin .../Stickers/BlobEmoji/blobnervous.png | Bin .../Stickers/BlobEmoji/blobnervous2.png | Bin .../BlobEmoji/blobnervouspleading.png | Bin .../Stickers/BlobEmoji/blobneutral.png | Bin .../Stickers/BlobEmoji/blobnight.png | Bin .../Stickers/BlobEmoji/blobninja.png | Bin .../Stickers/BlobEmoji/blobnitro.png | Bin .../Stickers/BlobEmoji/blobno.png | Bin .../Stickers/BlobEmoji/blobnogood.png | Bin .../Stickers/BlobEmoji/blobnom.png | Bin .../Stickers/BlobEmoji/blobnomchocolate.png | Bin .../Stickers/BlobEmoji/blobnomchristmas.png | Bin .../Stickers/BlobEmoji/blobnomcookie.png | Bin .../Stickers/BlobEmoji/blobnomglobal1.png | Bin .../Stickers/BlobEmoji/blobnomglobal2.png | Bin .../Stickers/BlobEmoji/blobnomglobal3.png | Bin .../Stickers/BlobEmoji/blobnomouth.png | Bin .../Stickers/BlobEmoji/blobnook.png | Bin .../Stickers/BlobEmoji/blobnostar.png | Bin .../Stickers/BlobEmoji/blobnostar2.png | Bin .../Stickers/BlobEmoji/blobnwn.png | Bin .../Stickers/BlobEmoji/blobok.png | Bin .../Stickers/BlobEmoji/blobokhand.png | Bin .../Stickers/BlobEmoji/blobomo.png | Bin .../Stickers/BlobEmoji/blobonfire.png | Bin .../Stickers/BlobEmoji/blobono.png | Bin .../Stickers/BlobEmoji/blobooh.png | Bin .../Stickers/BlobEmoji/bloboohcry.png | Bin .../Stickers/BlobEmoji/blobopenmouth.png | Bin .../Stickers/BlobEmoji/bloboro.png | Bin .../Stickers/BlobEmoji/bloboutage.png | Bin .../Stickers/BlobEmoji/bloboverheated.png | Bin .../Stickers/BlobEmoji/blobovo.png | Bin .../Stickers/BlobEmoji/blobowo.png | Bin .../Stickers/BlobEmoji/blobowo2.png | Bin .../Stickers/BlobEmoji/blobowoevil.png | Bin .../Stickers/BlobEmoji/blobowosquint.png | Bin .../Stickers/BlobEmoji/blobpain.png | Bin .../Stickers/BlobEmoji/blobpainpats.png | Bin .../Stickers/BlobEmoji/blobpan.png | Bin .../Stickers/BlobEmoji/blobpanic.png | Bin .../Stickers/BlobEmoji/blobpanic2.png | Bin .../Stickers/BlobEmoji/blobpartlysunny.png | Bin .../Stickers/BlobEmoji/blobparty.png | Bin .../Stickers/BlobEmoji/blobpatrol.png | Bin .../Stickers/BlobEmoji/blobpats.png | Bin .../Stickers/BlobEmoji/blobpeek.png | Bin .../Stickers/BlobEmoji/blobpensive.png | Bin .../Stickers/BlobEmoji/blobpensivepray.png | Bin .../Stickers/BlobEmoji/blobpin.png | Bin .../Stickers/BlobEmoji/blobpirate.png | Bin .../Stickers/BlobEmoji/blobpleading.png | Bin .../Stickers/BlobEmoji/blobpolice.png | Bin .../Stickers/BlobEmoji/blobpoliceangery.png | Bin .../Stickers/BlobEmoji/blobpoll.png | Bin .../Stickers/BlobEmoji/blobpopcorn.png | Bin .../Stickers/BlobEmoji/blobpopsicle.png | Bin .../Stickers/BlobEmoji/blobpout.png | Bin .../Stickers/BlobEmoji/blobpout2.png | Bin .../Stickers/BlobEmoji/blobpray.png | Bin .../Stickers/BlobEmoji/blobpumpkin.png | Bin .../Stickers/BlobEmoji/blobrage.png | Bin .../Stickers/BlobEmoji/blobrageangry.png | Bin .../Stickers/BlobEmoji/blobreach.png | Bin .../Stickers/BlobEmoji/blobreachdrool.png | Bin .../Stickers/BlobEmoji/blobreachfront.png | Bin .../Stickers/BlobEmoji/blobreachfrown.png | Bin .../Stickers/BlobEmoji/blobreachreverse.png | Bin .../Stickers/BlobEmoji/blobreachsob.png | Bin .../Stickers/BlobEmoji/blobrelieved.png | Bin .../Stickers/BlobEmoji/blobrofl.png | Bin .../Stickers/BlobEmoji/blobrollingeyes.png | Bin .../Stickers/BlobEmoji/blobross.png | Bin .../Stickers/BlobEmoji/blobsad.png | Bin .../Stickers/BlobEmoji/blobsadpats.png | Bin .../Stickers/BlobEmoji/blobsadrain.png | Bin .../Stickers/BlobEmoji/blobsalute.png | Bin .../Stickers/BlobEmoji/blobsanta.png | Bin .../Stickers/BlobEmoji/blobscarf.png | Bin .../Stickers/BlobEmoji/blobscream.png | Bin .../Stickers/BlobEmoji/blobsecret.png | Bin .../Stickers/BlobEmoji/blobshh.png | Bin .../Stickers/BlobEmoji/blobshrug.png | Bin .../Stickers/BlobEmoji/blobsick.png | Bin .../Stickers/BlobEmoji/blobsip.png | Bin .../Stickers/BlobEmoji/blobsleeping.png | Bin .../Stickers/BlobEmoji/blobsleepless.png | Bin .../Stickers/BlobEmoji/blobslightsmile.png | Bin .../Stickers/BlobEmoji/blobsmile.png | Bin .../Stickers/BlobEmoji/blobsmilehappy.png | Bin .../Stickers/BlobEmoji/blobsmilehappyeyes.png | Bin .../Stickers/BlobEmoji/blobsmilesweat.png | Bin .../Stickers/BlobEmoji/blobsmilesweat2.png | Bin .../Stickers/BlobEmoji/blobsmiletear.png | Bin .../Stickers/BlobEmoji/blobsmiley.png | Bin .../Stickers/BlobEmoji/blobsmirk.png | Bin .../Stickers/BlobEmoji/blobsmirk2.png | Bin .../Stickers/BlobEmoji/blobsneezing.png | Bin .../Stickers/BlobEmoji/blobsnuggle.png | Bin .../Stickers/BlobEmoji/blobsob.png | Bin .../Stickers/BlobEmoji/blobsobglasses.png | Bin .../Stickers/BlobEmoji/blobspam.png | Bin .../Stickers/BlobEmoji/blobsplosion.png | Bin .../Stickers/BlobEmoji/blobspy.png | Bin .../Stickers/BlobEmoji/blobsquee.png | Bin .../Stickers/BlobEmoji/blobstare.png | Bin .../Stickers/BlobEmoji/blobstarstruck.png | Bin .../Stickers/BlobEmoji/blobstop.png | Bin .../Stickers/BlobEmoji/blobstudent.png | Bin .../Stickers/BlobEmoji/blobsunglasses.png | Bin .../Stickers/BlobEmoji/blobsurprised.png | Bin .../Stickers/BlobEmoji/blobsus.png | Bin .../Stickers/BlobEmoji/blobsweats.png | Bin .../Stickers/BlobEmoji/blobsweatsweary.png | Bin .../Stickers/BlobEmoji/blobteefs.png | Bin .../Stickers/BlobEmoji/blobthanks.png | Bin .../Stickers/BlobEmoji/blobthief.png | Bin .../Stickers/BlobEmoji/blobthinking.png | Bin .../Stickers/BlobEmoji/blobthinkingcool.png | Bin .../Stickers/BlobEmoji/blobthinkingdown.png | Bin .../Stickers/BlobEmoji/blobthinkingeyes.png | Bin .../Stickers/BlobEmoji/blobthinkingfast.png | Bin .../Stickers/BlobEmoji/blobthinkingglare.png | Bin .../Stickers/BlobEmoji/blobthinkingsmirk.png | Bin .../Stickers/BlobEmoji/blobthinksmart.png | Bin .../Stickers/BlobEmoji/blobthis.png | Bin .../Stickers/BlobEmoji/blobthonkang.png | Bin .../Stickers/BlobEmoji/blobthumbsdown.png | Bin .../Stickers/BlobEmoji/blobthumbsup.png | Bin .../Stickers/BlobEmoji/blobthump.png | Bin .../Stickers/BlobEmoji/blobtilt.png | Bin .../Stickers/BlobEmoji/blobtired.png | Bin .../Stickers/BlobEmoji/blobtongue.png | Bin .../Stickers/BlobEmoji/blobtonguewink.png | Bin .../Stickers/BlobEmoji/blobtorch.png | Bin .../Stickers/BlobEmoji/blobtrans.png | Bin .../Stickers/BlobEmoji/blobtriumph.png | Bin .../Stickers/BlobEmoji/blobtriumph2.png | Bin .../Stickers/BlobEmoji/blobugh.png | Bin .../Stickers/BlobEmoji/blobunamused.png | Bin .../Stickers/BlobEmoji/blobunsure.png | Bin .../Stickers/BlobEmoji/blobupset.png | Bin .../Stickers/BlobEmoji/blobupsidedown.png | Bin .../Stickers/BlobEmoji/blobuwu.png | Bin .../Stickers/BlobEmoji/blobvomiting.png | Bin .../Stickers/BlobEmoji/blobwaitwhat.png | Bin .../Stickers/BlobEmoji/blobwave.png | Bin .../Stickers/BlobEmoji/blobwavereverse.png | Bin .../Stickers/BlobEmoji/blobwavesob.png | Bin .../Stickers/BlobEmoji/blobweary.png | Bin .../Stickers/BlobEmoji/blobwhistle.png | Bin .../Stickers/BlobEmoji/blobwink.png | Bin .../Stickers/BlobEmoji/blobwitch.png | Bin .../Stickers/BlobEmoji/blobwizard.png | Bin .../Stickers/BlobEmoji/blobwoah.png | Bin .../Stickers/BlobEmoji/blobwoahopenmouth.png | Bin .../Stickers/BlobEmoji/blobwob.png | Bin .../Stickers/BlobEmoji/blobwooloo.png | Bin .../Stickers/BlobEmoji/blobwoozy.png | Bin .../Stickers/BlobEmoji/blobworker.png | Bin .../Stickers/BlobEmoji/blobworried.png | Bin .../Stickers/BlobEmoji/blobxd.png | Bin .../Stickers/BlobEmoji/blobyawn.png | Bin .../Stickers/BlobEmoji/blobyes.png | Bin .../Stickers/BlobEmoji/blobyikes.png | Bin .../Stickers/BlobEmoji/blobyum.png | Bin .../Stickers/BlobEmoji/blobzippermouth.png | Bin .../Stickers/BlobEmoji/bolb.png | Bin .../Stickers/BlobEmoji/doggoblob.png | Bin .../Stickers/BlobEmoji/feelsblobman.png | Bin .../Stickers/BlobEmoji/ferretblob.png | Bin .../Stickers/BlobEmoji/gentleblob.png | Bin .../Stickers/BlobEmoji/googlebear.png | Bin .../Stickers/BlobEmoji/googlebee.png | Bin .../Stickers/BlobEmoji/googlebird.png | Bin .../Stickers/BlobEmoji/googleblueheart.png | Bin .../Stickers/BlobEmoji/googlecake.png | Bin .../Stickers/BlobEmoji/googlecat.png | Bin .../Stickers/BlobEmoji/googlecatface.png | Bin .../Stickers/BlobEmoji/googlecatheart.png | Bin .../Stickers/BlobEmoji/googlechick.png | Bin .../Stickers/BlobEmoji/googlechicken.png | Bin .../BlobEmoji/googlechristmastree.png | Bin .../Stickers/BlobEmoji/googlecow.png | Bin .../Stickers/BlobEmoji/googlecrab.png | Bin .../Stickers/BlobEmoji/googledog.png | Bin .../Stickers/BlobEmoji/googledove.png | Bin .../Stickers/BlobEmoji/googleduck.png | Bin .../Stickers/BlobEmoji/googleeagle.png | Bin .../Stickers/BlobEmoji/googlefire.png | Bin .../Stickers/BlobEmoji/googlefox.png | Bin .../Stickers/BlobEmoji/googleghost.png | Bin .../Stickers/BlobEmoji/googlegift.png | Bin .../Stickers/BlobEmoji/googlegoat.png | Bin .../Stickers/BlobEmoji/googlegun.png | Bin .../Stickers/BlobEmoji/googleicecream.png | Bin .../Stickers/BlobEmoji/googlekoala.png | Bin .../Stickers/BlobEmoji/googlelion.png | Bin .../Stickers/BlobEmoji/googlemouse.png | Bin .../Stickers/BlobEmoji/googlemuscleL.png | Bin .../Stickers/BlobEmoji/googlemuscleR.png | Bin .../Stickers/BlobEmoji/googleoctopus.png | Bin .../Stickers/BlobEmoji/googlepanda.png | Bin .../Stickers/BlobEmoji/googlepenguin.png | Bin .../Stickers/BlobEmoji/googlepig.png | Bin .../Stickers/BlobEmoji/googlepizza.png | Bin .../Stickers/BlobEmoji/googlerabbit.png | Bin .../Stickers/BlobEmoji/googlerat.png | Bin .../Stickers/BlobEmoji/googleredheart.png | Bin .../Stickers/BlobEmoji/googlescorpion.png | Bin .../Stickers/BlobEmoji/googlesheep.png | Bin .../Stickers/BlobEmoji/googlesnail.png | Bin .../Stickers/BlobEmoji/googlesnake.png | Bin .../Stickers/BlobEmoji/googlesquirrel.png | Bin .../Stickers/BlobEmoji/googleturtle.png | Bin .../Stickers/BlobEmoji/googlewhale.png | Bin .../Stickers/BlobEmoji/greentick.png | Bin .../Stickers/BlobEmoji/jakeblob.png | Bin .../Stickers/BlobEmoji/kirbyblob.png | Bin .../Stickers/BlobEmoji/nellyblob.png | Bin .../Stickers/BlobEmoji/nikoblob.png | Bin .../Stickers/BlobEmoji/notlikeblob.png | Bin .../Stickers/BlobEmoji/pandablob.png | Bin .../Stickers/BlobEmoji/photoblob.png | Bin .../Stickers/BlobEmoji/pikablob.png | Bin .../Stickers/BlobEmoji/pusheenblob.png | Bin .../Stickers/BlobEmoji/rainblob.png | Bin .../Stickers/BlobEmoji/redtick.png | Bin .../Stickers/BlobEmoji/reindeerblob.png | Bin .../Stickers/BlobEmoji/rickblob.png | Bin .../Stickers/BlobEmoji/superblob.png | Bin .../Stickers/BlobEmoji/thinkingwithblobs.png | Bin .../Stickers/BlobEmoji/wolfiriblob.png | Bin .../Stickers/BlobEmoji/wumpusblob.png | Bin SnapX.Core/SnapX.Core.csproj | 2 +- 391 files changed, 1092 insertions(+), 5 deletions(-) rename SnapX.Core/{ScreenCapture => SharpCapture}/Animations/BaseAnimation.cs (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Animations/ColorBlinkAnimation.cs (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Animations/OpacityAnimation.cs (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Animations/PointAnimation.cs (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Animations/RectangleAnimation.cs (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Animations/TextAnimation.cs (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Helpers/InputManager.cs (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Helpers/LocationInfo.cs (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Helpers/SimpleWindowInfo.cs (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Helpers/SnapSize.cs (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Helpers/WindowsList.cs (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Rust/Cargo.lock (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Rust/Cargo.toml (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Rust/bindings/snapxrust.cs (100%) create mode 100644 SnapX.Core/SharpCapture/Rust/bindings/snapxrust.py rename SnapX.Core/{ScreenCapture => SharpCapture}/Rust/build.rs (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Rust/src/lib.rs (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Rust/src/snapxrust.udl (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/ScreenRecording/FFmpegCaptureDevice.cs (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/ScreenRecording/FFmpegOptions.cs (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/ScreenRecording/HardDiskCache.cs (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/ScreenRecording/ImageCache.cs (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/ScreenRecording/ScreenRecorder.cs (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/ScreenRecording/ScreenRecordingOptions.cs (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/b1nzyblob.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/b1nzyblob2.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/b4nzyblob.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blob.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blob0w0.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blob3c.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blob3cevil.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobaffection.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobamused.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobangel.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobangery.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobangry.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobangry2.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobangrypuff.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobartist.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobaviator.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobawkward.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobaww.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobbandage.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobbanhammer.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobbathtub.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobblackcat.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobblush.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobboost.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobbored.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobbot.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobbowing.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobbroken.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobcamera.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobcat.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobcheeky.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobcheer.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobcheerful.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobcheerful2.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobclipboard.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobcmereyou.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobcocoa.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobcomfort.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobconcerned.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobconfounded.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobconfused.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobcool.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobcouncil.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobcouple.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobcowboy.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobcry.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobdancer.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobdead.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobderpy.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobderpyhappy.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobdetective.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobdevil.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobdevilsmile.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobdisapproval.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobdisguise.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobdizzy.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobdizzy2.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobdoctor.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobdoubt.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobdoubtful.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobdrool.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobeagle.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobembarrassed.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobembarrassed2.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobenjoy.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/bloberm.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobexpressionless.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobeyesdown.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobeyesup.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobfacemask.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobfacepalm.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobfearful.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobfingerguns.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobfingerscrossed.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobfirefighter.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobfistbumpL.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobfistbumpR.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobflushed.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobfreezing.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobfrog.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobfrown.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobfrowning.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobfrowningbig.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobgamer.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobgift.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobgiggle.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobglare.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobglarepolice.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobglassesdown.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobgo.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobgoat.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobgoodmorning.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobgoodmorningreverse.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobgoodnight.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobgoodnightreverse.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobgrimace.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobgrin.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobgrumpy.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobheart.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobhearteyes.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobhero.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobhighfive.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobhug.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobhug2.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobhuh.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobhushed.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobhyperthink.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobhyperthinkfast.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobhypesquad.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobidea.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobimfine.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobinlove.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobjam.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobjoy.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobkiss.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobkissblush.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobkissheart.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/bloblamp.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/bloblul.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobmail.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobmaracas.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobmelt.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobmeltblush.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobmeltsob.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobmeltsoblove.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobmindblown.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobmlem.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobmorning.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobmoustache.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobnauseated.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobnerd.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobnervous.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobnervous2.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobnervouspleading.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobneutral.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobnight.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobninja.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobnitro.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobno.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobnogood.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobnom.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobnomchocolate.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobnomchristmas.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobnomcookie.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobnomglobal1.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobnomglobal2.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobnomglobal3.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobnomouth.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobnook.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobnostar.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobnostar2.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobnwn.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobok.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobokhand.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobomo.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobonfire.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobono.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobooh.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/bloboohcry.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobopenmouth.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/bloboro.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/bloboutage.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/bloboverheated.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobovo.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobowo.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobowo2.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobowoevil.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobowosquint.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobpain.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobpainpats.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobpan.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobpanic.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobpanic2.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobpartlysunny.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobparty.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobpatrol.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobpats.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobpeek.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobpensive.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobpensivepray.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobpin.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobpirate.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobpleading.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobpolice.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobpoliceangery.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobpoll.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobpopcorn.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobpopsicle.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobpout.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobpout2.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobpray.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobpumpkin.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobrage.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobrageangry.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobreach.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobreachdrool.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobreachfront.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobreachfrown.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobreachreverse.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobreachsob.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobrelieved.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobrofl.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobrollingeyes.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobross.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsad.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsadpats.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsadrain.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsalute.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsanta.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobscarf.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobscream.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsecret.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobshh.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobshrug.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsick.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsip.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsleeping.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsleepless.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobslightsmile.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsmile.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsmilehappy.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsmilehappyeyes.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsmilesweat.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsmilesweat2.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsmiletear.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsmiley.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsmirk.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsmirk2.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsneezing.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsnuggle.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsob.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsobglasses.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobspam.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsplosion.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobspy.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsquee.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobstare.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobstarstruck.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobstop.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobstudent.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsunglasses.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsurprised.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsus.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsweats.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobsweatsweary.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobteefs.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobthanks.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobthief.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobthinking.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobthinkingcool.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobthinkingdown.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobthinkingeyes.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobthinkingfast.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobthinkingglare.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobthinkingsmirk.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobthinksmart.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobthis.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobthonkang.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobthumbsdown.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobthumbsup.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobthump.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobtilt.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobtired.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobtongue.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobtonguewink.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobtorch.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobtrans.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobtriumph.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobtriumph2.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobugh.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobunamused.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobunsure.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobupset.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobupsidedown.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobuwu.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobvomiting.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobwaitwhat.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobwave.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobwavereverse.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobwavesob.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobweary.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobwhistle.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobwink.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobwitch.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobwizard.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobwoah.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobwoahopenmouth.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobwob.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobwooloo.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobwoozy.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobworker.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobworried.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobxd.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobyawn.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobyes.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobyikes.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobyum.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/blobzippermouth.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/bolb.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/doggoblob.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/feelsblobman.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/ferretblob.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/gentleblob.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlebear.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlebee.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlebird.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googleblueheart.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlecake.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlecat.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlecatface.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlecatheart.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlechick.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlechicken.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlechristmastree.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlecow.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlecrab.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googledog.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googledove.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googleduck.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googleeagle.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlefire.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlefox.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googleghost.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlegift.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlegoat.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlegun.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googleicecream.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlekoala.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlelion.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlemouse.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlemuscleL.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlemuscleR.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googleoctopus.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlepanda.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlepenguin.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlepig.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlepizza.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlerabbit.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlerat.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googleredheart.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlescorpion.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlesheep.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlesnail.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlesnake.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlesquirrel.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googleturtle.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/googlewhale.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/greentick.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/jakeblob.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/kirbyblob.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/nellyblob.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/nikoblob.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/notlikeblob.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/pandablob.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/photoblob.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/pikablob.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/pusheenblob.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/rainblob.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/redtick.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/reindeerblob.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/rickblob.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/superblob.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/thinkingwithblobs.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/wolfiriblob.png (100%) rename SnapX.Core/{ScreenCapture => SharpCapture}/Stickers/BlobEmoji/wumpusblob.png (100%) diff --git a/SnapX.Core/OSX.props b/SnapX.Core/OSX.props index 6056f8154..9dc0bc302 100644 --- a/SnapX.Core/OSX.props +++ b/SnapX.Core/OSX.props @@ -1,10 +1,7 @@ - - libsnapxrust.dylib - - + diff --git a/SnapX.Core/ScreenCapture/Animations/BaseAnimation.cs b/SnapX.Core/SharpCapture/Animations/BaseAnimation.cs similarity index 100% rename from SnapX.Core/ScreenCapture/Animations/BaseAnimation.cs rename to SnapX.Core/SharpCapture/Animations/BaseAnimation.cs diff --git a/SnapX.Core/ScreenCapture/Animations/ColorBlinkAnimation.cs b/SnapX.Core/SharpCapture/Animations/ColorBlinkAnimation.cs similarity index 100% rename from SnapX.Core/ScreenCapture/Animations/ColorBlinkAnimation.cs rename to SnapX.Core/SharpCapture/Animations/ColorBlinkAnimation.cs diff --git a/SnapX.Core/ScreenCapture/Animations/OpacityAnimation.cs b/SnapX.Core/SharpCapture/Animations/OpacityAnimation.cs similarity index 100% rename from SnapX.Core/ScreenCapture/Animations/OpacityAnimation.cs rename to SnapX.Core/SharpCapture/Animations/OpacityAnimation.cs diff --git a/SnapX.Core/ScreenCapture/Animations/PointAnimation.cs b/SnapX.Core/SharpCapture/Animations/PointAnimation.cs similarity index 100% rename from SnapX.Core/ScreenCapture/Animations/PointAnimation.cs rename to SnapX.Core/SharpCapture/Animations/PointAnimation.cs diff --git a/SnapX.Core/ScreenCapture/Animations/RectangleAnimation.cs b/SnapX.Core/SharpCapture/Animations/RectangleAnimation.cs similarity index 100% rename from SnapX.Core/ScreenCapture/Animations/RectangleAnimation.cs rename to SnapX.Core/SharpCapture/Animations/RectangleAnimation.cs diff --git a/SnapX.Core/ScreenCapture/Animations/TextAnimation.cs b/SnapX.Core/SharpCapture/Animations/TextAnimation.cs similarity index 100% rename from SnapX.Core/ScreenCapture/Animations/TextAnimation.cs rename to SnapX.Core/SharpCapture/Animations/TextAnimation.cs diff --git a/SnapX.Core/ScreenCapture/Helpers/InputManager.cs b/SnapX.Core/SharpCapture/Helpers/InputManager.cs similarity index 100% rename from SnapX.Core/ScreenCapture/Helpers/InputManager.cs rename to SnapX.Core/SharpCapture/Helpers/InputManager.cs diff --git a/SnapX.Core/ScreenCapture/Helpers/LocationInfo.cs b/SnapX.Core/SharpCapture/Helpers/LocationInfo.cs similarity index 100% rename from SnapX.Core/ScreenCapture/Helpers/LocationInfo.cs rename to SnapX.Core/SharpCapture/Helpers/LocationInfo.cs diff --git a/SnapX.Core/ScreenCapture/Helpers/SimpleWindowInfo.cs b/SnapX.Core/SharpCapture/Helpers/SimpleWindowInfo.cs similarity index 100% rename from SnapX.Core/ScreenCapture/Helpers/SimpleWindowInfo.cs rename to SnapX.Core/SharpCapture/Helpers/SimpleWindowInfo.cs diff --git a/SnapX.Core/ScreenCapture/Helpers/SnapSize.cs b/SnapX.Core/SharpCapture/Helpers/SnapSize.cs similarity index 100% rename from SnapX.Core/ScreenCapture/Helpers/SnapSize.cs rename to SnapX.Core/SharpCapture/Helpers/SnapSize.cs diff --git a/SnapX.Core/ScreenCapture/Helpers/WindowsList.cs b/SnapX.Core/SharpCapture/Helpers/WindowsList.cs similarity index 100% rename from SnapX.Core/ScreenCapture/Helpers/WindowsList.cs rename to SnapX.Core/SharpCapture/Helpers/WindowsList.cs diff --git a/SnapX.Core/ScreenCapture/Rust/Cargo.lock b/SnapX.Core/SharpCapture/Rust/Cargo.lock similarity index 100% rename from SnapX.Core/ScreenCapture/Rust/Cargo.lock rename to SnapX.Core/SharpCapture/Rust/Cargo.lock diff --git a/SnapX.Core/ScreenCapture/Rust/Cargo.toml b/SnapX.Core/SharpCapture/Rust/Cargo.toml similarity index 100% rename from SnapX.Core/ScreenCapture/Rust/Cargo.toml rename to SnapX.Core/SharpCapture/Rust/Cargo.toml diff --git a/SnapX.Core/ScreenCapture/Rust/bindings/snapxrust.cs b/SnapX.Core/SharpCapture/Rust/bindings/snapxrust.cs similarity index 100% rename from SnapX.Core/ScreenCapture/Rust/bindings/snapxrust.cs rename to SnapX.Core/SharpCapture/Rust/bindings/snapxrust.cs diff --git a/SnapX.Core/SharpCapture/Rust/bindings/snapxrust.py b/SnapX.Core/SharpCapture/Rust/bindings/snapxrust.py new file mode 100644 index 000000000..a8186a831 --- /dev/null +++ b/SnapX.Core/SharpCapture/Rust/bindings/snapxrust.py @@ -0,0 +1,1090 @@ +# This file was autogenerated by some hot garbage in the `uniffi` crate. +# Trust me, you don't want to mess with it! + +# Common helper code. +# +# Ideally this would live in a separate .py file where it can be unittested etc +# in isolation, and perhaps even published as a re-useable package. +# +# However, it's important that the details of how this helper code works (e.g. the +# way that different builtin types are passed across the FFI) exactly match what's +# expected by the rust code on the other side of the interface. In practice right +# now that means coming from the exact some version of `uniffi` that was used to +# compile the rust component. The easiest way to ensure this is to bundle the Python +# helpers directly inline like we're doing here. + +import os +import sys +import ctypes +import enum +import struct +import contextlib +import datetime +import typing +import platform + +# Used for default argument values +_DEFAULT = object() + + +class _UniffiRustBuffer(ctypes.Structure): + _fields_ = [ + ("capacity", ctypes.c_int32), + ("len", ctypes.c_int32), + ("data", ctypes.POINTER(ctypes.c_char)), + ] + + @staticmethod + def alloc(size): + return _rust_call(_UniffiLib.ffi_snapxrust_rustbuffer_alloc, size) + + @staticmethod + def reserve(rbuf, additional): + return _rust_call(_UniffiLib.ffi_snapxrust_rustbuffer_reserve, rbuf, additional) + + def free(self): + return _rust_call(_UniffiLib.ffi_snapxrust_rustbuffer_free, self) + + def __str__(self): + return "_UniffiRustBuffer(capacity={}, len={}, data={})".format( + self.capacity, + self.len, + self.data[0:self.len] + ) + + @contextlib.contextmanager + def alloc_with_builder(*args): + """Context-manger to allocate a buffer using a _UniffiRustBufferBuilder. + + The allocated buffer will be automatically freed if an error occurs, ensuring that + we don't accidentally leak it. + """ + builder = _UniffiRustBufferBuilder() + try: + yield builder + except: + builder.discard() + raise + + @contextlib.contextmanager + def consume_with_stream(self): + """Context-manager to consume a buffer using a _UniffiRustBufferStream. + + The _UniffiRustBuffer will be freed once the context-manager exits, ensuring that we don't + leak it even if an error occurs. + """ + try: + s = _UniffiRustBufferStream.from_rust_buffer(self) + yield s + if s.remaining() != 0: + raise RuntimeError("junk data left in buffer at end of consume_with_stream") + finally: + self.free() + + @contextlib.contextmanager + def read_with_stream(self): + """Context-manager to read a buffer using a _UniffiRustBufferStream. + + This is like consume_with_stream, but doesn't free the buffer afterwards. + It should only be used with borrowed `_UniffiRustBuffer` data. + """ + s = _UniffiRustBufferStream.from_rust_buffer(self) + yield s + if s.remaining() != 0: + raise RuntimeError("junk data left in buffer at end of read_with_stream") + +class _UniffiForeignBytes(ctypes.Structure): + _fields_ = [ + ("len", ctypes.c_int32), + ("data", ctypes.POINTER(ctypes.c_char)), + ] + + def __str__(self): + return "_UniffiForeignBytes(len={}, data={})".format(self.len, self.data[0:self.len]) + + +class _UniffiRustBufferStream: + """ + Helper for structured reading of bytes from a _UniffiRustBuffer + """ + + def __init__(self, data, len): + self.data = data + self.len = len + self.offset = 0 + + @classmethod + def from_rust_buffer(cls, buf): + return cls(buf.data, buf.len) + + def remaining(self): + return self.len - self.offset + + def _unpack_from(self, size, format): + if self.offset + size > self.len: + raise InternalError("read past end of rust buffer") + value = struct.unpack(format, self.data[self.offset:self.offset+size])[0] + self.offset += size + return value + + def read(self, size): + if self.offset + size > self.len: + raise InternalError("read past end of rust buffer") + data = self.data[self.offset:self.offset+size] + self.offset += size + return data + + def read_i8(self): + return self._unpack_from(1, ">b") + + def read_u8(self): + return self._unpack_from(1, ">B") + + def read_i16(self): + return self._unpack_from(2, ">h") + + def read_u16(self): + return self._unpack_from(2, ">H") + + def read_i32(self): + return self._unpack_from(4, ">i") + + def read_u32(self): + return self._unpack_from(4, ">I") + + def read_i64(self): + return self._unpack_from(8, ">q") + + def read_u64(self): + return self._unpack_from(8, ">Q") + + def read_float(self): + v = self._unpack_from(4, ">f") + return v + + def read_double(self): + return self._unpack_from(8, ">d") + + def read_c_size_t(self): + return self._unpack_from(ctypes.sizeof(ctypes.c_size_t) , "@N") + +class _UniffiRustBufferBuilder: + """ + Helper for structured writing of bytes into a _UniffiRustBuffer. + """ + + def __init__(self): + self.rbuf = _UniffiRustBuffer.alloc(16) + self.rbuf.len = 0 + + def finalize(self): + rbuf = self.rbuf + self.rbuf = None + return rbuf + + def discard(self): + if self.rbuf is not None: + rbuf = self.finalize() + rbuf.free() + + @contextlib.contextmanager + def _reserve(self, num_bytes): + if self.rbuf.len + num_bytes > self.rbuf.capacity: + self.rbuf = _UniffiRustBuffer.reserve(self.rbuf, num_bytes) + yield None + self.rbuf.len += num_bytes + + def _pack_into(self, size, format, value): + with self._reserve(size): + # XXX TODO: I feel like I should be able to use `struct.pack_into` here but can't figure it out. + for i, byte in enumerate(struct.pack(format, value)): + self.rbuf.data[self.rbuf.len + i] = byte + + def write(self, value): + with self._reserve(len(value)): + for i, byte in enumerate(value): + self.rbuf.data[self.rbuf.len + i] = byte + + def write_i8(self, v): + self._pack_into(1, ">b", v) + + def write_u8(self, v): + self._pack_into(1, ">B", v) + + def write_i16(self, v): + self._pack_into(2, ">h", v) + + def write_u16(self, v): + self._pack_into(2, ">H", v) + + def write_i32(self, v): + self._pack_into(4, ">i", v) + + def write_u32(self, v): + self._pack_into(4, ">I", v) + + def write_i64(self, v): + self._pack_into(8, ">q", v) + + def write_u64(self, v): + self._pack_into(8, ">Q", v) + + def write_float(self, v): + self._pack_into(4, ">f", v) + + def write_double(self, v): + self._pack_into(8, ">d", v) + + def write_c_size_t(self, v): + self._pack_into(ctypes.sizeof(ctypes.c_size_t) , "@N", v) +# A handful of classes and functions to support the generated data structures. +# This would be a good candidate for isolating in its own ffi-support lib. + +class InternalError(Exception): + pass + +class _UniffiRustCallStatus(ctypes.Structure): + """ + Error runtime. + """ + _fields_ = [ + ("code", ctypes.c_int8), + ("error_buf", _UniffiRustBuffer), + ] + + # These match the values from the uniffi::rustcalls module + CALL_SUCCESS = 0 + CALL_ERROR = 1 + CALL_PANIC = 2 + + def __str__(self): + if self.code == _UniffiRustCallStatus.CALL_SUCCESS: + return "_UniffiRustCallStatus(CALL_SUCCESS)" + elif self.code == _UniffiRustCallStatus.CALL_ERROR: + return "_UniffiRustCallStatus(CALL_ERROR)" + elif self.code == _UniffiRustCallStatus.CALL_PANIC: + return "_UniffiRustCallStatus(CALL_PANIC)" + else: + return "_UniffiRustCallStatus()" + +def _rust_call(fn, *args): + # Call a rust function + return _rust_call_with_error(None, fn, *args) + +def _rust_call_with_error(error_ffi_converter, fn, *args): + # Call a rust function and handle any errors + # + # This function is used for rust calls that return Result<> and therefore can set the CALL_ERROR status code. + # error_ffi_converter must be set to the _UniffiConverter for the error class that corresponds to the result. + call_status = _UniffiRustCallStatus(code=_UniffiRustCallStatus.CALL_SUCCESS, error_buf=_UniffiRustBuffer(0, 0, None)) + + args_with_error = args + (ctypes.byref(call_status),) + result = fn(*args_with_error) + _uniffi_check_call_status(error_ffi_converter, call_status) + return result + +def _uniffi_check_call_status(error_ffi_converter, call_status): + if call_status.code == _UniffiRustCallStatus.CALL_SUCCESS: + pass + elif call_status.code == _UniffiRustCallStatus.CALL_ERROR: + if error_ffi_converter is None: + call_status.error_buf.free() + raise InternalError("_rust_call_with_error: CALL_ERROR, but error_ffi_converter is None") + else: + raise error_ffi_converter.lift(call_status.error_buf) + elif call_status.code == _UniffiRustCallStatus.CALL_PANIC: + # When the rust code sees a panic, it tries to construct a _UniffiRustBuffer + # with the message. But if that code panics, then it just sends back + # an empty buffer. + if call_status.error_buf.len > 0: + msg = _UniffiConverterString.lift(call_status.error_buf) + else: + msg = "Unknown rust panic" + raise InternalError(msg) + else: + raise InternalError("Invalid _UniffiRustCallStatus code: {}".format( + call_status.code)) + +# A function pointer for a callback as defined by UniFFI. +# Rust definition `fn(handle: u64, method: u32, args: _UniffiRustBuffer, buf_ptr: *mut _UniffiRustBuffer) -> int` +_UNIFFI_FOREIGN_CALLBACK_T = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_ulonglong, ctypes.c_ulong, ctypes.POINTER(ctypes.c_char), ctypes.c_int, ctypes.POINTER(_UniffiRustBuffer)) + +# UniFFI future continuation +_UNIFFI_FUTURE_CONTINUATION_T = ctypes.CFUNCTYPE(None, ctypes.c_size_t, ctypes.c_int8) + +class _UniffiPointerManagerCPython: + """ + Manage giving out pointers to Python objects on CPython + + This class is used to generate opaque pointers that reference Python objects to pass to Rust. + It assumes a CPython platform. See _UniffiPointerManagerGeneral for the alternative. + """ + + def new_pointer(self, obj): + """ + Get a pointer for an object as a ctypes.c_size_t instance + + Each call to new_pointer() must be balanced with exactly one call to release_pointer() + + This returns a ctypes.c_size_t. This is always the same size as a pointer and can be + interchanged with pointers for FFI function arguments and return values. + """ + # IncRef the object since we're going to pass a pointer to Rust + ctypes.pythonapi.Py_IncRef(ctypes.py_object(obj)) + # id() is the object address on CPython + # (https://docs.python.org/3/library/functions.html#id) + return id(obj) + + def release_pointer(self, address): + py_obj = ctypes.cast(address, ctypes.py_object) + obj = py_obj.value + ctypes.pythonapi.Py_DecRef(py_obj) + return obj + + def lookup(self, address): + return ctypes.cast(address, ctypes.py_object).value + +class _UniffiPointerManagerGeneral: + """ + Manage giving out pointers to Python objects on non-CPython platforms + + This has the same API as _UniffiPointerManagerCPython, but doesn't assume we're running on + CPython and is slightly slower. + + Instead of using real pointers, it maps integer values to objects and returns the keys as + c_size_t values. + """ + + def __init__(self): + self._map = {} + self._lock = threading.Lock() + self._current_handle = 0 + + def new_pointer(self, obj): + with self._lock: + handle = self._current_handle + self._current_handle += 1 + self._map[handle] = obj + return handle + + def release_pointer(self, handle): + with self._lock: + return self._map.pop(handle) + + def lookup(self, handle): + with self._lock: + return self._map[handle] + +# Pick an pointer manager implementation based on the platform +if platform.python_implementation() == 'CPython': + _UniffiPointerManager = _UniffiPointerManagerCPython # type: ignore +else: + _UniffiPointerManager = _UniffiPointerManagerGeneral # type: ignore +# Types conforming to `_UniffiConverterPrimitive` pass themselves directly over the FFI. +class _UniffiConverterPrimitive: + @classmethod + def check(cls, value): + return value + + @classmethod + def lift(cls, value): + return value + + @classmethod + def lower(cls, value): + return cls.lowerUnchecked(cls.check(value)) + + @classmethod + def lowerUnchecked(cls, value): + return value + + @classmethod + def write(cls, value, buf): + cls.write_unchecked(cls.check(value), buf) + +class _UniffiConverterPrimitiveInt(_UniffiConverterPrimitive): + @classmethod + def check(cls, value): + try: + value = value.__index__() + except Exception: + raise TypeError("'{}' object cannot be interpreted as an integer".format(type(value).__name__)) + if not isinstance(value, int): + raise TypeError("__index__ returned non-int (type {})".format(type(value).__name__)) + if not cls.VALUE_MIN <= value < cls.VALUE_MAX: + raise ValueError("{} requires {} <= value < {}".format(cls.CLASS_NAME, cls.VALUE_MIN, cls.VALUE_MAX)) + return super().check(value) + +class _UniffiConverterPrimitiveFloat(_UniffiConverterPrimitive): + @classmethod + def check(cls, value): + try: + value = value.__float__() + except Exception: + raise TypeError("must be real number, not {}".format(type(value).__name__)) + if not isinstance(value, float): + raise TypeError("__float__ returned non-float (type {})".format(type(value).__name__)) + return super().check(value) + +# Helper class for wrapper types that will always go through a _UniffiRustBuffer. +# Classes should inherit from this and implement the `read` and `write` static methods. +class _UniffiConverterRustBuffer: + @classmethod + def lift(cls, rbuf): + with rbuf.consume_with_stream() as stream: + return cls.read(stream) + + @classmethod + def lower(cls, value): + with _UniffiRustBuffer.alloc_with_builder() as builder: + cls.write(value, builder) + return builder.finalize() + +# Contains loading, initialization code, and the FFI Function declarations. +# Define some ctypes FFI types that we use in the library + +""" +ctypes type for the foreign executor callback. This is a built-in interface for scheduling +tasks + +Args: + executor: opaque c_size_t value representing the eventloop + delay: delay in ms + task: function pointer to the task callback + task_data: void pointer to the task callback data + +Normally we should call task(task_data) after the detail. +However, when task is NULL this indicates that Rust has dropped the ForeignExecutor and we should +decrease the EventLoop refcount. +""" +_UNIFFI_FOREIGN_EXECUTOR_CALLBACK_T = ctypes.CFUNCTYPE(ctypes.c_int8, ctypes.c_size_t, ctypes.c_uint32, ctypes.c_void_p, ctypes.c_void_p) + +""" +Function pointer for a Rust task, which a callback function that takes a opaque pointer +""" +_UNIFFI_RUST_TASK = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_int8) + +def _uniffi_future_callback_t(return_type): + """ + Factory function to create callback function types for async functions + """ + return ctypes.CFUNCTYPE(None, ctypes.c_size_t, return_type, _UniffiRustCallStatus) + +def _uniffi_load_indirect(): + """ + This is how we find and load the dynamic library provided by the component. + For now we just look it up by name. + """ + if sys.platform == "darwin": + libname = "lib{}.dylib" + elif sys.platform.startswith("win"): + # As of python3.8, ctypes does not seem to search $PATH when loading DLLs. + # We could use `os.add_dll_directory` to configure the search path, but + # it doesn't feel right to mess with application-wide settings. Let's + # assume that the `.dll` is next to the `.py` file and load by full path. + libname = os.path.join( + os.path.dirname(__file__), + "{}.dll", + ) + else: + # Anything else must be an ELF platform - Linux, *BSD, Solaris/illumos + libname = "lib{}.so" + + libname = libname.format("uniffi_snapxrust") + path = os.path.join(os.path.dirname(__file__), libname) + lib = ctypes.cdll.LoadLibrary(path) + return lib + +def _uniffi_check_contract_api_version(lib): + # Get the bindings contract version from our ComponentInterface + bindings_contract_version = 24 + # Get the scaffolding contract version by calling the into the dylib + scaffolding_contract_version = lib.ffi_snapxrust_uniffi_contract_version() + if bindings_contract_version != scaffolding_contract_version: + raise InternalError("UniFFI contract version mismatch: try cleaning and rebuilding your project") + +def _uniffi_check_api_checksums(lib): + if lib.uniffi_snapxrust_checksum_func_capture_fullscreen() != 6651: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_snapxrust_checksum_func_capture_monitor() != 61593: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_snapxrust_checksum_func_capture_rect() != 15851: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_snapxrust_checksum_func_capture_window() != 52724: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_snapxrust_checksum_func_get_monitor() != 61273: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_snapxrust_checksum_func_get_primary_monitor() != 12932: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_snapxrust_checksum_func_get_screen_dimensions() != 25884: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_snapxrust_checksum_func_get_working_area() != 60391: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + +# A ctypes library to expose the extern-C FFI definitions. +# This is an implementation detail which will be called internally by the public API. + +_UniffiLib = _uniffi_load_indirect() +_UniffiLib.uniffi_snapxrust_fn_func_capture_fullscreen.argtypes = ( + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_snapxrust_fn_func_capture_fullscreen.restype = _UniffiRustBuffer +_UniffiLib.uniffi_snapxrust_fn_func_capture_monitor.argtypes = ( + _UniffiRustBuffer, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_snapxrust_fn_func_capture_monitor.restype = _UniffiRustBuffer +_UniffiLib.uniffi_snapxrust_fn_func_capture_rect.argtypes = ( + ctypes.c_uint32, + ctypes.c_uint32, + ctypes.c_uint32, + ctypes.c_uint32, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_snapxrust_fn_func_capture_rect.restype = _UniffiRustBuffer +_UniffiLib.uniffi_snapxrust_fn_func_capture_window.argtypes = ( + ctypes.c_uint32, + ctypes.c_uint32, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_snapxrust_fn_func_capture_window.restype = _UniffiRustBuffer +_UniffiLib.uniffi_snapxrust_fn_func_get_monitor.argtypes = ( + ctypes.c_uint32, + ctypes.c_uint32, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_snapxrust_fn_func_get_monitor.restype = _UniffiRustBuffer +_UniffiLib.uniffi_snapxrust_fn_func_get_primary_monitor.argtypes = ( + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_snapxrust_fn_func_get_primary_monitor.restype = _UniffiRustBuffer +_UniffiLib.uniffi_snapxrust_fn_func_get_screen_dimensions.argtypes = ( + _UniffiRustBuffer, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_snapxrust_fn_func_get_screen_dimensions.restype = _UniffiRustBuffer +_UniffiLib.uniffi_snapxrust_fn_func_get_working_area.argtypes = ( + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_snapxrust_fn_func_get_working_area.restype = _UniffiRustBuffer +_UniffiLib.ffi_snapxrust_rustbuffer_alloc.argtypes = ( + ctypes.c_int32, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_snapxrust_rustbuffer_alloc.restype = _UniffiRustBuffer +_UniffiLib.ffi_snapxrust_rustbuffer_from_bytes.argtypes = ( + _UniffiForeignBytes, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_snapxrust_rustbuffer_from_bytes.restype = _UniffiRustBuffer +_UniffiLib.ffi_snapxrust_rustbuffer_free.argtypes = ( + _UniffiRustBuffer, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_snapxrust_rustbuffer_free.restype = None +_UniffiLib.ffi_snapxrust_rustbuffer_reserve.argtypes = ( + _UniffiRustBuffer, + ctypes.c_int32, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_snapxrust_rustbuffer_reserve.restype = _UniffiRustBuffer +_UniffiLib.ffi_snapxrust_rust_future_continuation_callback_set.argtypes = ( + _UNIFFI_FUTURE_CONTINUATION_T, +) +_UniffiLib.ffi_snapxrust_rust_future_continuation_callback_set.restype = None +_UniffiLib.ffi_snapxrust_rust_future_poll_u8.argtypes = ( + ctypes.c_void_p, + ctypes.c_size_t, +) +_UniffiLib.ffi_snapxrust_rust_future_poll_u8.restype = None +_UniffiLib.ffi_snapxrust_rust_future_cancel_u8.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_cancel_u8.restype = None +_UniffiLib.ffi_snapxrust_rust_future_free_u8.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_free_u8.restype = None +_UniffiLib.ffi_snapxrust_rust_future_complete_u8.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_snapxrust_rust_future_complete_u8.restype = ctypes.c_uint8 +_UniffiLib.ffi_snapxrust_rust_future_poll_i8.argtypes = ( + ctypes.c_void_p, + ctypes.c_size_t, +) +_UniffiLib.ffi_snapxrust_rust_future_poll_i8.restype = None +_UniffiLib.ffi_snapxrust_rust_future_cancel_i8.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_cancel_i8.restype = None +_UniffiLib.ffi_snapxrust_rust_future_free_i8.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_free_i8.restype = None +_UniffiLib.ffi_snapxrust_rust_future_complete_i8.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_snapxrust_rust_future_complete_i8.restype = ctypes.c_int8 +_UniffiLib.ffi_snapxrust_rust_future_poll_u16.argtypes = ( + ctypes.c_void_p, + ctypes.c_size_t, +) +_UniffiLib.ffi_snapxrust_rust_future_poll_u16.restype = None +_UniffiLib.ffi_snapxrust_rust_future_cancel_u16.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_cancel_u16.restype = None +_UniffiLib.ffi_snapxrust_rust_future_free_u16.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_free_u16.restype = None +_UniffiLib.ffi_snapxrust_rust_future_complete_u16.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_snapxrust_rust_future_complete_u16.restype = ctypes.c_uint16 +_UniffiLib.ffi_snapxrust_rust_future_poll_i16.argtypes = ( + ctypes.c_void_p, + ctypes.c_size_t, +) +_UniffiLib.ffi_snapxrust_rust_future_poll_i16.restype = None +_UniffiLib.ffi_snapxrust_rust_future_cancel_i16.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_cancel_i16.restype = None +_UniffiLib.ffi_snapxrust_rust_future_free_i16.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_free_i16.restype = None +_UniffiLib.ffi_snapxrust_rust_future_complete_i16.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_snapxrust_rust_future_complete_i16.restype = ctypes.c_int16 +_UniffiLib.ffi_snapxrust_rust_future_poll_u32.argtypes = ( + ctypes.c_void_p, + ctypes.c_size_t, +) +_UniffiLib.ffi_snapxrust_rust_future_poll_u32.restype = None +_UniffiLib.ffi_snapxrust_rust_future_cancel_u32.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_cancel_u32.restype = None +_UniffiLib.ffi_snapxrust_rust_future_free_u32.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_free_u32.restype = None +_UniffiLib.ffi_snapxrust_rust_future_complete_u32.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_snapxrust_rust_future_complete_u32.restype = ctypes.c_uint32 +_UniffiLib.ffi_snapxrust_rust_future_poll_i32.argtypes = ( + ctypes.c_void_p, + ctypes.c_size_t, +) +_UniffiLib.ffi_snapxrust_rust_future_poll_i32.restype = None +_UniffiLib.ffi_snapxrust_rust_future_cancel_i32.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_cancel_i32.restype = None +_UniffiLib.ffi_snapxrust_rust_future_free_i32.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_free_i32.restype = None +_UniffiLib.ffi_snapxrust_rust_future_complete_i32.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_snapxrust_rust_future_complete_i32.restype = ctypes.c_int32 +_UniffiLib.ffi_snapxrust_rust_future_poll_u64.argtypes = ( + ctypes.c_void_p, + ctypes.c_size_t, +) +_UniffiLib.ffi_snapxrust_rust_future_poll_u64.restype = None +_UniffiLib.ffi_snapxrust_rust_future_cancel_u64.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_cancel_u64.restype = None +_UniffiLib.ffi_snapxrust_rust_future_free_u64.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_free_u64.restype = None +_UniffiLib.ffi_snapxrust_rust_future_complete_u64.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_snapxrust_rust_future_complete_u64.restype = ctypes.c_uint64 +_UniffiLib.ffi_snapxrust_rust_future_poll_i64.argtypes = ( + ctypes.c_void_p, + ctypes.c_size_t, +) +_UniffiLib.ffi_snapxrust_rust_future_poll_i64.restype = None +_UniffiLib.ffi_snapxrust_rust_future_cancel_i64.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_cancel_i64.restype = None +_UniffiLib.ffi_snapxrust_rust_future_free_i64.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_free_i64.restype = None +_UniffiLib.ffi_snapxrust_rust_future_complete_i64.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_snapxrust_rust_future_complete_i64.restype = ctypes.c_int64 +_UniffiLib.ffi_snapxrust_rust_future_poll_f32.argtypes = ( + ctypes.c_void_p, + ctypes.c_size_t, +) +_UniffiLib.ffi_snapxrust_rust_future_poll_f32.restype = None +_UniffiLib.ffi_snapxrust_rust_future_cancel_f32.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_cancel_f32.restype = None +_UniffiLib.ffi_snapxrust_rust_future_free_f32.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_free_f32.restype = None +_UniffiLib.ffi_snapxrust_rust_future_complete_f32.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_snapxrust_rust_future_complete_f32.restype = ctypes.c_float +_UniffiLib.ffi_snapxrust_rust_future_poll_f64.argtypes = ( + ctypes.c_void_p, + ctypes.c_size_t, +) +_UniffiLib.ffi_snapxrust_rust_future_poll_f64.restype = None +_UniffiLib.ffi_snapxrust_rust_future_cancel_f64.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_cancel_f64.restype = None +_UniffiLib.ffi_snapxrust_rust_future_free_f64.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_free_f64.restype = None +_UniffiLib.ffi_snapxrust_rust_future_complete_f64.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_snapxrust_rust_future_complete_f64.restype = ctypes.c_double +_UniffiLib.ffi_snapxrust_rust_future_poll_pointer.argtypes = ( + ctypes.c_void_p, + ctypes.c_size_t, +) +_UniffiLib.ffi_snapxrust_rust_future_poll_pointer.restype = None +_UniffiLib.ffi_snapxrust_rust_future_cancel_pointer.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_cancel_pointer.restype = None +_UniffiLib.ffi_snapxrust_rust_future_free_pointer.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_free_pointer.restype = None +_UniffiLib.ffi_snapxrust_rust_future_complete_pointer.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_snapxrust_rust_future_complete_pointer.restype = ctypes.c_void_p +_UniffiLib.ffi_snapxrust_rust_future_poll_rust_buffer.argtypes = ( + ctypes.c_void_p, + ctypes.c_size_t, +) +_UniffiLib.ffi_snapxrust_rust_future_poll_rust_buffer.restype = None +_UniffiLib.ffi_snapxrust_rust_future_cancel_rust_buffer.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_cancel_rust_buffer.restype = None +_UniffiLib.ffi_snapxrust_rust_future_free_rust_buffer.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_free_rust_buffer.restype = None +_UniffiLib.ffi_snapxrust_rust_future_complete_rust_buffer.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_snapxrust_rust_future_complete_rust_buffer.restype = _UniffiRustBuffer +_UniffiLib.ffi_snapxrust_rust_future_poll_void.argtypes = ( + ctypes.c_void_p, + ctypes.c_size_t, +) +_UniffiLib.ffi_snapxrust_rust_future_poll_void.restype = None +_UniffiLib.ffi_snapxrust_rust_future_cancel_void.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_cancel_void.restype = None +_UniffiLib.ffi_snapxrust_rust_future_free_void.argtypes = ( + ctypes.c_void_p, +) +_UniffiLib.ffi_snapxrust_rust_future_free_void.restype = None +_UniffiLib.ffi_snapxrust_rust_future_complete_void.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_snapxrust_rust_future_complete_void.restype = None +_UniffiLib.uniffi_snapxrust_checksum_func_capture_fullscreen.argtypes = ( +) +_UniffiLib.uniffi_snapxrust_checksum_func_capture_fullscreen.restype = ctypes.c_uint16 +_UniffiLib.uniffi_snapxrust_checksum_func_capture_monitor.argtypes = ( +) +_UniffiLib.uniffi_snapxrust_checksum_func_capture_monitor.restype = ctypes.c_uint16 +_UniffiLib.uniffi_snapxrust_checksum_func_capture_rect.argtypes = ( +) +_UniffiLib.uniffi_snapxrust_checksum_func_capture_rect.restype = ctypes.c_uint16 +_UniffiLib.uniffi_snapxrust_checksum_func_capture_window.argtypes = ( +) +_UniffiLib.uniffi_snapxrust_checksum_func_capture_window.restype = ctypes.c_uint16 +_UniffiLib.uniffi_snapxrust_checksum_func_get_monitor.argtypes = ( +) +_UniffiLib.uniffi_snapxrust_checksum_func_get_monitor.restype = ctypes.c_uint16 +_UniffiLib.uniffi_snapxrust_checksum_func_get_primary_monitor.argtypes = ( +) +_UniffiLib.uniffi_snapxrust_checksum_func_get_primary_monitor.restype = ctypes.c_uint16 +_UniffiLib.uniffi_snapxrust_checksum_func_get_screen_dimensions.argtypes = ( +) +_UniffiLib.uniffi_snapxrust_checksum_func_get_screen_dimensions.restype = ctypes.c_uint16 +_UniffiLib.uniffi_snapxrust_checksum_func_get_working_area.argtypes = ( +) +_UniffiLib.uniffi_snapxrust_checksum_func_get_working_area.restype = ctypes.c_uint16 +_UniffiLib.ffi_snapxrust_uniffi_contract_version.argtypes = ( +) +_UniffiLib.ffi_snapxrust_uniffi_contract_version.restype = ctypes.c_uint32 +_uniffi_check_contract_api_version(_UniffiLib) +_uniffi_check_api_checksums(_UniffiLib) + +# Async support + +# Public interface members begin here. + + +class _UniffiConverterUInt32(_UniffiConverterPrimitiveInt): + CLASS_NAME = "u32" + VALUE_MIN = 0 + VALUE_MAX = 2**32 + + @staticmethod + def read(buf): + return buf.read_u32() + + @staticmethod + def write_unchecked(value, buf): + buf.write_u32(value) + +class _UniffiConverterInt32(_UniffiConverterPrimitiveInt): + CLASS_NAME = "i32" + VALUE_MIN = -2**31 + VALUE_MAX = 2**31 + + @staticmethod + def read(buf): + return buf.read_i32() + + @staticmethod + def write_unchecked(value, buf): + buf.write_i32(value) + +class _UniffiConverterString: + @staticmethod + def check(value): + if not isinstance(value, str): + raise TypeError("argument must be str, not {}".format(type(value).__name__)) + return value + + @staticmethod + def read(buf): + size = buf.read_i32() + if size < 0: + raise InternalError("Unexpected negative string length") + utf8_bytes = buf.read(size) + return utf8_bytes.decode("utf-8") + + @staticmethod + def write(value, buf): + value = _UniffiConverterString.check(value) + utf8_bytes = value.encode("utf-8") + buf.write_i32(len(utf8_bytes)) + buf.write(utf8_bytes) + + @staticmethod + def lift(buf): + with buf.consume_with_stream() as stream: + return stream.read(stream.remaining()).decode("utf-8") + + @staticmethod + def lower(value): + value = _UniffiConverterString.check(value) + with _UniffiRustBuffer.alloc_with_builder() as builder: + builder.write(value.encode("utf-8")) + return builder.finalize() + +class _UniffiConverterBytes(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + size = buf.read_i32() + if size < 0: + raise InternalError("Unexpected negative byte string length") + return buf.read(size) + + @staticmethod + def write(value, buf): + try: + memoryview(value) + except TypeError: + raise TypeError("a bytes-like object is required, not {!r}".format(type(value).__name__)) + buf.write_i32(len(value)) + buf.write(value) + + +class ImageData: + image: "bytes";width: "int";height: "int"; + + @typing.no_type_check + def __init__(self, image: "bytes", width: "int", height: "int"): + self.image = image + self.width = width + self.height = height + + def __str__(self): + return "ImageData(image={}, width={}, height={})".format(self.image, self.width, self.height) + + def __eq__(self, other): + if self.image != other.image: + return False + if self.width != other.width: + return False + if self.height != other.height: + return False + return True + +class _UniffiConverterTypeImageData(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + return ImageData( + image=_UniffiConverterBytes.read(buf), + width=_UniffiConverterUInt32.read(buf), + height=_UniffiConverterUInt32.read(buf), + ) + + @staticmethod + def write(value, buf): + _UniffiConverterBytes.write(value.image, buf) + _UniffiConverterUInt32.write(value.width, buf) + _UniffiConverterUInt32.write(value.height, buf) + + +class MonitorData: + width: "int";height: "int";x: "int";y: "int";name: "str"; + + @typing.no_type_check + def __init__(self, width: "int", height: "int", x: "int", y: "int", name: "str"): + self.width = width + self.height = height + self.x = x + self.y = y + self.name = name + + def __str__(self): + return "MonitorData(width={}, height={}, x={}, y={}, name={})".format(self.width, self.height, self.x, self.y, self.name) + + def __eq__(self, other): + if self.width != other.width: + return False + if self.height != other.height: + return False + if self.x != other.x: + return False + if self.y != other.y: + return False + if self.name != other.name: + return False + return True + +class _UniffiConverterTypeMonitorData(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + return MonitorData( + width=_UniffiConverterUInt32.read(buf), + height=_UniffiConverterUInt32.read(buf), + x=_UniffiConverterInt32.read(buf), + y=_UniffiConverterInt32.read(buf), + name=_UniffiConverterString.read(buf), + ) + + @staticmethod + def write(value, buf): + _UniffiConverterUInt32.write(value.width, buf) + _UniffiConverterUInt32.write(value.height, buf) + _UniffiConverterInt32.write(value.x, buf) + _UniffiConverterInt32.write(value.y, buf) + _UniffiConverterString.write(value.name, buf) + +def capture_fullscreen() -> "ImageData": + return _UniffiConverterTypeImageData.lift(_rust_call(_UniffiLib.uniffi_snapxrust_fn_func_capture_fullscreen,)) + + +def capture_monitor(name: "str") -> "ImageData": + + return _UniffiConverterTypeImageData.lift(_rust_call(_UniffiLib.uniffi_snapxrust_fn_func_capture_monitor, + _UniffiConverterString.lower(name))) + + +def capture_rect(x: "int",y: "int",width: "int",height: "int") -> "ImageData": + + + + + return _UniffiConverterTypeImageData.lift(_rust_call(_UniffiLib.uniffi_snapxrust_fn_func_capture_rect, + _UniffiConverterUInt32.lower(x), + _UniffiConverterUInt32.lower(y), + _UniffiConverterUInt32.lower(width), + _UniffiConverterUInt32.lower(height))) + + +def capture_window(x: "int",y: "int") -> "ImageData": + + + return _UniffiConverterTypeImageData.lift(_rust_call(_UniffiLib.uniffi_snapxrust_fn_func_capture_window, + _UniffiConverterUInt32.lower(x), + _UniffiConverterUInt32.lower(y))) + + +def get_monitor(x: "int",y: "int") -> "MonitorData": + + + return _UniffiConverterTypeMonitorData.lift(_rust_call(_UniffiLib.uniffi_snapxrust_fn_func_get_monitor, + _UniffiConverterUInt32.lower(x), + _UniffiConverterUInt32.lower(y))) + + +def get_primary_monitor() -> "MonitorData": + return _UniffiConverterTypeMonitorData.lift(_rust_call(_UniffiLib.uniffi_snapxrust_fn_func_get_primary_monitor,)) + + +def get_screen_dimensions(name: "str") -> "MonitorData": + + return _UniffiConverterTypeMonitorData.lift(_rust_call(_UniffiLib.uniffi_snapxrust_fn_func_get_screen_dimensions, + _UniffiConverterString.lower(name))) + + +def get_working_area() -> "MonitorData": + return _UniffiConverterTypeMonitorData.lift(_rust_call(_UniffiLib.uniffi_snapxrust_fn_func_get_working_area,)) + + +__all__ = [ + "InternalError", + "ImageData", + "MonitorData", + "capture_fullscreen", + "capture_monitor", + "capture_rect", + "capture_window", + "get_monitor", + "get_primary_monitor", + "get_screen_dimensions", + "get_working_area", +] + diff --git a/SnapX.Core/ScreenCapture/Rust/build.rs b/SnapX.Core/SharpCapture/Rust/build.rs similarity index 100% rename from SnapX.Core/ScreenCapture/Rust/build.rs rename to SnapX.Core/SharpCapture/Rust/build.rs diff --git a/SnapX.Core/ScreenCapture/Rust/src/lib.rs b/SnapX.Core/SharpCapture/Rust/src/lib.rs similarity index 100% rename from SnapX.Core/ScreenCapture/Rust/src/lib.rs rename to SnapX.Core/SharpCapture/Rust/src/lib.rs diff --git a/SnapX.Core/ScreenCapture/Rust/src/snapxrust.udl b/SnapX.Core/SharpCapture/Rust/src/snapxrust.udl similarity index 100% rename from SnapX.Core/ScreenCapture/Rust/src/snapxrust.udl rename to SnapX.Core/SharpCapture/Rust/src/snapxrust.udl diff --git a/SnapX.Core/ScreenCapture/ScreenRecording/FFmpegCaptureDevice.cs b/SnapX.Core/SharpCapture/ScreenRecording/FFmpegCaptureDevice.cs similarity index 100% rename from SnapX.Core/ScreenCapture/ScreenRecording/FFmpegCaptureDevice.cs rename to SnapX.Core/SharpCapture/ScreenRecording/FFmpegCaptureDevice.cs diff --git a/SnapX.Core/ScreenCapture/ScreenRecording/FFmpegOptions.cs b/SnapX.Core/SharpCapture/ScreenRecording/FFmpegOptions.cs similarity index 100% rename from SnapX.Core/ScreenCapture/ScreenRecording/FFmpegOptions.cs rename to SnapX.Core/SharpCapture/ScreenRecording/FFmpegOptions.cs diff --git a/SnapX.Core/ScreenCapture/ScreenRecording/HardDiskCache.cs b/SnapX.Core/SharpCapture/ScreenRecording/HardDiskCache.cs similarity index 100% rename from SnapX.Core/ScreenCapture/ScreenRecording/HardDiskCache.cs rename to SnapX.Core/SharpCapture/ScreenRecording/HardDiskCache.cs diff --git a/SnapX.Core/ScreenCapture/ScreenRecording/ImageCache.cs b/SnapX.Core/SharpCapture/ScreenRecording/ImageCache.cs similarity index 100% rename from SnapX.Core/ScreenCapture/ScreenRecording/ImageCache.cs rename to SnapX.Core/SharpCapture/ScreenRecording/ImageCache.cs diff --git a/SnapX.Core/ScreenCapture/ScreenRecording/ScreenRecorder.cs b/SnapX.Core/SharpCapture/ScreenRecording/ScreenRecorder.cs similarity index 100% rename from SnapX.Core/ScreenCapture/ScreenRecording/ScreenRecorder.cs rename to SnapX.Core/SharpCapture/ScreenRecording/ScreenRecorder.cs diff --git a/SnapX.Core/ScreenCapture/ScreenRecording/ScreenRecordingOptions.cs b/SnapX.Core/SharpCapture/ScreenRecording/ScreenRecordingOptions.cs similarity index 100% rename from SnapX.Core/ScreenCapture/ScreenRecording/ScreenRecordingOptions.cs rename to SnapX.Core/SharpCapture/ScreenRecording/ScreenRecordingOptions.cs diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/b1nzyblob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/b1nzyblob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/b1nzyblob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/b1nzyblob.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/b1nzyblob2.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/b1nzyblob2.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/b1nzyblob2.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/b1nzyblob2.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/b4nzyblob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/b4nzyblob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/b4nzyblob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/b4nzyblob.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blob.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blob0w0.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blob0w0.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blob0w0.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blob0w0.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blob3c.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blob3c.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blob3c.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blob3c.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blob3cevil.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blob3cevil.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blob3cevil.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blob3cevil.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobaffection.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobaffection.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobaffection.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobaffection.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobamused.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobamused.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobamused.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobamused.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobangel.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobangel.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobangel.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobangel.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobangery.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobangery.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobangery.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobangery.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobangry.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobangry.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobangry.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobangry.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobangry2.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobangry2.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobangry2.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobangry2.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobangrypuff.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobangrypuff.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobangrypuff.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobangrypuff.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobartist.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobartist.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobartist.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobartist.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobaviator.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobaviator.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobaviator.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobaviator.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobawkward.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobawkward.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobawkward.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobawkward.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobaww.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobaww.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobaww.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobaww.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobbandage.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobbandage.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobbandage.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobbandage.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobbanhammer.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobbanhammer.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobbanhammer.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobbanhammer.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobbathtub.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobbathtub.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobbathtub.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobbathtub.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobblackcat.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobblackcat.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobblackcat.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobblackcat.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobblush.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobblush.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobblush.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobblush.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobboost.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobboost.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobboost.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobboost.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobbored.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobbored.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobbored.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobbored.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobbot.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobbot.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobbot.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobbot.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobbowing.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobbowing.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobbowing.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobbowing.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobbroken.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobbroken.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobbroken.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobbroken.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcamera.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcamera.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcamera.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcamera.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcat.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcat.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcat.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcat.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcheeky.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcheeky.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcheeky.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcheeky.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcheer.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcheer.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcheer.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcheer.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcheerful.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcheerful.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcheerful.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcheerful.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcheerful2.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcheerful2.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcheerful2.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcheerful2.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobclipboard.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobclipboard.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobclipboard.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobclipboard.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcmereyou.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcmereyou.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcmereyou.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcmereyou.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcocoa.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcocoa.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcocoa.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcocoa.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcomfort.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcomfort.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcomfort.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcomfort.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobconcerned.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobconcerned.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobconcerned.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobconcerned.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobconfounded.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobconfounded.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobconfounded.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobconfounded.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobconfused.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobconfused.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobconfused.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobconfused.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcool.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcool.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcool.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcool.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcouncil.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcouncil.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcouncil.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcouncil.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcouple.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcouple.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcouple.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcouple.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcowboy.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcowboy.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcowboy.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcowboy.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcry.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcry.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobcry.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobcry.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdancer.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdancer.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdancer.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdancer.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdead.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdead.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdead.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdead.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobderpy.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobderpy.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobderpy.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobderpy.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobderpyhappy.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobderpyhappy.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobderpyhappy.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobderpyhappy.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdetective.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdetective.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdetective.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdetective.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdevil.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdevil.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdevil.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdevil.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdevilsmile.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdevilsmile.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdevilsmile.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdevilsmile.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdisapproval.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdisapproval.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdisapproval.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdisapproval.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdisguise.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdisguise.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdisguise.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdisguise.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdizzy.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdizzy.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdizzy.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdizzy.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdizzy2.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdizzy2.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdizzy2.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdizzy2.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdoctor.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdoctor.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdoctor.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdoctor.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdoubt.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdoubt.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdoubt.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdoubt.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdoubtful.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdoubtful.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdoubtful.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdoubtful.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdrool.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdrool.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobdrool.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobdrool.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobeagle.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobeagle.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobeagle.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobeagle.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobembarrassed.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobembarrassed.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobembarrassed.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobembarrassed.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobembarrassed2.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobembarrassed2.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobembarrassed2.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobembarrassed2.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobenjoy.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobenjoy.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobenjoy.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobenjoy.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/bloberm.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/bloberm.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/bloberm.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/bloberm.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobexpressionless.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobexpressionless.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobexpressionless.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobexpressionless.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobeyesdown.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobeyesdown.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobeyesdown.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobeyesdown.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobeyesup.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobeyesup.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobeyesup.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobeyesup.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfacemask.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfacemask.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfacemask.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfacemask.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfacepalm.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfacepalm.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfacepalm.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfacepalm.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfearful.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfearful.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfearful.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfearful.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfingerguns.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfingerguns.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfingerguns.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfingerguns.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfingerscrossed.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfingerscrossed.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfingerscrossed.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfingerscrossed.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfirefighter.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfirefighter.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfirefighter.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfirefighter.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfistbumpL.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfistbumpL.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfistbumpL.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfistbumpL.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfistbumpR.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfistbumpR.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfistbumpR.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfistbumpR.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobflushed.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobflushed.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobflushed.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobflushed.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfreezing.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfreezing.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfreezing.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfreezing.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfrog.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfrog.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfrog.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfrog.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfrown.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfrown.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfrown.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfrown.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfrowning.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfrowning.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfrowning.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfrowning.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfrowningbig.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfrowningbig.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobfrowningbig.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobfrowningbig.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobgamer.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobgamer.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobgamer.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobgamer.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobgift.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobgift.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobgift.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobgift.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobgiggle.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobgiggle.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobgiggle.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobgiggle.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobglare.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobglare.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobglare.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobglare.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobglarepolice.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobglarepolice.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobglarepolice.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobglarepolice.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobglassesdown.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobglassesdown.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobglassesdown.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobglassesdown.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobgo.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobgo.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobgo.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobgo.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobgoat.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobgoat.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobgoat.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobgoat.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobgoodmorning.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobgoodmorning.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobgoodmorning.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobgoodmorning.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobgoodmorningreverse.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobgoodmorningreverse.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobgoodmorningreverse.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobgoodmorningreverse.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobgoodnight.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobgoodnight.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobgoodnight.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobgoodnight.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobgoodnightreverse.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobgoodnightreverse.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobgoodnightreverse.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobgoodnightreverse.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobgrimace.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobgrimace.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobgrimace.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobgrimace.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobgrin.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobgrin.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobgrin.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobgrin.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobgrumpy.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobgrumpy.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobgrumpy.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobgrumpy.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobheart.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobheart.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobheart.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobheart.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobhearteyes.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobhearteyes.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobhearteyes.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobhearteyes.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobhero.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobhero.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobhero.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobhero.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobhighfive.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobhighfive.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobhighfive.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobhighfive.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobhug.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobhug.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobhug.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobhug.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobhug2.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobhug2.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobhug2.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobhug2.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobhuh.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobhuh.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobhuh.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobhuh.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobhushed.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobhushed.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobhushed.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobhushed.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobhyperthink.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobhyperthink.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobhyperthink.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobhyperthink.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobhyperthinkfast.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobhyperthinkfast.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobhyperthinkfast.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobhyperthinkfast.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobhypesquad.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobhypesquad.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobhypesquad.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobhypesquad.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobidea.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobidea.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobidea.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobidea.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobimfine.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobimfine.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobimfine.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobimfine.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobinlove.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobinlove.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobinlove.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobinlove.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobjam.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobjam.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobjam.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobjam.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobjoy.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobjoy.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobjoy.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobjoy.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobkiss.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobkiss.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobkiss.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobkiss.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobkissblush.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobkissblush.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobkissblush.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobkissblush.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobkissheart.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobkissheart.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobkissheart.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobkissheart.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/bloblamp.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/bloblamp.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/bloblamp.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/bloblamp.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/bloblul.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/bloblul.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/bloblul.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/bloblul.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobmail.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobmail.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobmail.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobmail.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobmaracas.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobmaracas.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobmaracas.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobmaracas.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobmelt.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobmelt.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobmelt.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobmelt.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobmeltblush.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobmeltblush.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobmeltblush.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobmeltblush.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobmeltsob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobmeltsob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobmeltsob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobmeltsob.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobmeltsoblove.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobmeltsoblove.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobmeltsoblove.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobmeltsoblove.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobmindblown.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobmindblown.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobmindblown.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobmindblown.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobmlem.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobmlem.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobmlem.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobmlem.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobmorning.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobmorning.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobmorning.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobmorning.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobmoustache.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobmoustache.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobmoustache.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobmoustache.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnauseated.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnauseated.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnauseated.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnauseated.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnerd.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnerd.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnerd.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnerd.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnervous.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnervous.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnervous.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnervous.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnervous2.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnervous2.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnervous2.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnervous2.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnervouspleading.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnervouspleading.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnervouspleading.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnervouspleading.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobneutral.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobneutral.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobneutral.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobneutral.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnight.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnight.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnight.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnight.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobninja.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobninja.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobninja.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobninja.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnitro.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnitro.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnitro.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnitro.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobno.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobno.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobno.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobno.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnogood.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnogood.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnogood.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnogood.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnom.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnom.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnom.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnom.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnomchocolate.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnomchocolate.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnomchocolate.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnomchocolate.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnomchristmas.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnomchristmas.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnomchristmas.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnomchristmas.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnomcookie.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnomcookie.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnomcookie.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnomcookie.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnomglobal1.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnomglobal1.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnomglobal1.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnomglobal1.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnomglobal2.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnomglobal2.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnomglobal2.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnomglobal2.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnomglobal3.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnomglobal3.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnomglobal3.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnomglobal3.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnomouth.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnomouth.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnomouth.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnomouth.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnook.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnook.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnook.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnook.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnostar.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnostar.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnostar.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnostar.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnostar2.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnostar2.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnostar2.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnostar2.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnwn.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnwn.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobnwn.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobnwn.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobok.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobok.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobok.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobok.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobokhand.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobokhand.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobokhand.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobokhand.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobomo.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobomo.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobomo.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobomo.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobonfire.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobonfire.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobonfire.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobonfire.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobono.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobono.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobono.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobono.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobooh.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobooh.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobooh.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobooh.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/bloboohcry.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/bloboohcry.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/bloboohcry.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/bloboohcry.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobopenmouth.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobopenmouth.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobopenmouth.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobopenmouth.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/bloboro.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/bloboro.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/bloboro.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/bloboro.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/bloboutage.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/bloboutage.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/bloboutage.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/bloboutage.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/bloboverheated.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/bloboverheated.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/bloboverheated.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/bloboverheated.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobovo.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobovo.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobovo.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobovo.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobowo.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobowo.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobowo.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobowo.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobowo2.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobowo2.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobowo2.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobowo2.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobowoevil.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobowoevil.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobowoevil.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobowoevil.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobowosquint.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobowosquint.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobowosquint.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobowosquint.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpain.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpain.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpain.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpain.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpainpats.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpainpats.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpainpats.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpainpats.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpan.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpan.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpan.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpan.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpanic.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpanic.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpanic.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpanic.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpanic2.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpanic2.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpanic2.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpanic2.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpartlysunny.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpartlysunny.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpartlysunny.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpartlysunny.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobparty.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobparty.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobparty.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobparty.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpatrol.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpatrol.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpatrol.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpatrol.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpats.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpats.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpats.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpats.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpeek.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpeek.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpeek.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpeek.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpensive.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpensive.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpensive.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpensive.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpensivepray.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpensivepray.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpensivepray.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpensivepray.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpin.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpin.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpin.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpin.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpirate.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpirate.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpirate.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpirate.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpleading.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpleading.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpleading.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpleading.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpolice.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpolice.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpolice.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpolice.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpoliceangery.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpoliceangery.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpoliceangery.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpoliceangery.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpoll.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpoll.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpoll.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpoll.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpopcorn.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpopcorn.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpopcorn.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpopcorn.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpopsicle.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpopsicle.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpopsicle.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpopsicle.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpout.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpout.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpout.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpout.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpout2.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpout2.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpout2.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpout2.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpray.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpray.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpray.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpray.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpumpkin.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpumpkin.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobpumpkin.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobpumpkin.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobrage.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobrage.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobrage.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobrage.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobrageangry.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobrageangry.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobrageangry.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobrageangry.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobreach.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobreach.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobreach.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobreach.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobreachdrool.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobreachdrool.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobreachdrool.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobreachdrool.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobreachfront.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobreachfront.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobreachfront.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobreachfront.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobreachfrown.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobreachfrown.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobreachfrown.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobreachfrown.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobreachreverse.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobreachreverse.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobreachreverse.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobreachreverse.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobreachsob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobreachsob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobreachsob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobreachsob.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobrelieved.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobrelieved.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobrelieved.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobrelieved.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobrofl.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobrofl.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobrofl.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobrofl.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobrollingeyes.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobrollingeyes.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobrollingeyes.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobrollingeyes.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobross.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobross.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobross.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobross.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsad.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsad.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsad.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsad.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsadpats.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsadpats.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsadpats.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsadpats.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsadrain.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsadrain.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsadrain.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsadrain.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsalute.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsalute.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsalute.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsalute.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsanta.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsanta.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsanta.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsanta.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobscarf.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobscarf.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobscarf.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobscarf.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobscream.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobscream.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobscream.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobscream.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsecret.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsecret.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsecret.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsecret.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobshh.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobshh.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobshh.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobshh.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobshrug.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobshrug.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobshrug.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobshrug.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsick.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsick.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsick.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsick.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsip.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsip.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsip.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsip.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsleeping.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsleeping.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsleeping.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsleeping.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsleepless.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsleepless.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsleepless.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsleepless.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobslightsmile.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobslightsmile.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobslightsmile.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobslightsmile.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsmile.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsmile.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsmile.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsmile.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsmilehappy.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsmilehappy.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsmilehappy.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsmilehappy.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsmilehappyeyes.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsmilehappyeyes.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsmilehappyeyes.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsmilehappyeyes.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsmilesweat.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsmilesweat.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsmilesweat.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsmilesweat.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsmilesweat2.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsmilesweat2.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsmilesweat2.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsmilesweat2.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsmiletear.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsmiletear.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsmiletear.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsmiletear.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsmiley.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsmiley.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsmiley.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsmiley.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsmirk.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsmirk.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsmirk.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsmirk.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsmirk2.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsmirk2.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsmirk2.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsmirk2.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsneezing.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsneezing.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsneezing.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsneezing.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsnuggle.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsnuggle.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsnuggle.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsnuggle.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsob.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsobglasses.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsobglasses.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsobglasses.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsobglasses.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobspam.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobspam.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobspam.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobspam.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsplosion.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsplosion.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsplosion.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsplosion.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobspy.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobspy.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobspy.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobspy.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsquee.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsquee.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsquee.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsquee.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobstare.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobstare.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobstare.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobstare.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobstarstruck.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobstarstruck.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobstarstruck.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobstarstruck.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobstop.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobstop.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobstop.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobstop.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobstudent.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobstudent.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobstudent.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobstudent.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsunglasses.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsunglasses.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsunglasses.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsunglasses.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsurprised.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsurprised.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsurprised.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsurprised.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsus.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsus.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsus.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsus.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsweats.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsweats.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsweats.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsweats.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsweatsweary.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsweatsweary.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobsweatsweary.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobsweatsweary.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobteefs.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobteefs.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobteefs.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobteefs.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthanks.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthanks.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthanks.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthanks.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthief.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthief.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthief.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthief.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthinking.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthinking.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthinking.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthinking.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthinkingcool.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthinkingcool.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthinkingcool.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthinkingcool.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthinkingdown.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthinkingdown.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthinkingdown.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthinkingdown.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthinkingeyes.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthinkingeyes.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthinkingeyes.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthinkingeyes.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthinkingfast.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthinkingfast.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthinkingfast.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthinkingfast.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthinkingglare.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthinkingglare.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthinkingglare.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthinkingglare.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthinkingsmirk.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthinkingsmirk.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthinkingsmirk.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthinkingsmirk.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthinksmart.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthinksmart.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthinksmart.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthinksmart.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthis.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthis.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthis.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthis.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthonkang.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthonkang.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthonkang.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthonkang.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthumbsdown.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthumbsdown.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthumbsdown.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthumbsdown.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthumbsup.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthumbsup.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthumbsup.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthumbsup.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthump.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthump.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobthump.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobthump.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobtilt.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobtilt.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobtilt.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobtilt.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobtired.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobtired.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobtired.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobtired.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobtongue.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobtongue.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobtongue.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobtongue.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobtonguewink.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobtonguewink.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobtonguewink.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobtonguewink.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobtorch.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobtorch.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobtorch.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobtorch.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobtrans.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobtrans.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobtrans.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobtrans.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobtriumph.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobtriumph.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobtriumph.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobtriumph.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobtriumph2.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobtriumph2.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobtriumph2.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobtriumph2.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobugh.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobugh.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobugh.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobugh.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobunamused.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobunamused.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobunamused.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobunamused.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobunsure.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobunsure.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobunsure.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobunsure.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobupset.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobupset.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobupset.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobupset.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobupsidedown.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobupsidedown.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobupsidedown.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobupsidedown.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobuwu.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobuwu.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobuwu.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobuwu.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobvomiting.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobvomiting.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobvomiting.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobvomiting.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwaitwhat.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwaitwhat.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwaitwhat.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwaitwhat.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwave.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwave.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwave.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwave.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwavereverse.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwavereverse.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwavereverse.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwavereverse.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwavesob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwavesob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwavesob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwavesob.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobweary.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobweary.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobweary.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobweary.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwhistle.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwhistle.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwhistle.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwhistle.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwink.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwink.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwink.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwink.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwitch.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwitch.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwitch.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwitch.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwizard.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwizard.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwizard.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwizard.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwoah.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwoah.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwoah.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwoah.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwoahopenmouth.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwoahopenmouth.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwoahopenmouth.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwoahopenmouth.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwob.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwooloo.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwooloo.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwooloo.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwooloo.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwoozy.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwoozy.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobwoozy.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobwoozy.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobworker.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobworker.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobworker.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobworker.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobworried.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobworried.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobworried.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobworried.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobxd.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobxd.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobxd.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobxd.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobyawn.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobyawn.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobyawn.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobyawn.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobyes.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobyes.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobyes.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobyes.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobyikes.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobyikes.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobyikes.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobyikes.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobyum.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobyum.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobyum.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobyum.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobzippermouth.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobzippermouth.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/blobzippermouth.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/blobzippermouth.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/bolb.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/bolb.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/bolb.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/bolb.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/doggoblob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/doggoblob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/doggoblob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/doggoblob.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/feelsblobman.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/feelsblobman.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/feelsblobman.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/feelsblobman.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/ferretblob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/ferretblob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/ferretblob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/ferretblob.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/gentleblob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/gentleblob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/gentleblob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/gentleblob.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlebear.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlebear.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlebear.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlebear.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlebee.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlebee.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlebee.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlebee.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlebird.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlebird.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlebird.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlebird.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googleblueheart.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googleblueheart.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googleblueheart.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googleblueheart.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlecake.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlecake.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlecake.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlecake.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlecat.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlecat.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlecat.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlecat.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlecatface.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlecatface.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlecatface.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlecatface.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlecatheart.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlecatheart.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlecatheart.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlecatheart.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlechick.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlechick.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlechick.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlechick.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlechicken.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlechicken.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlechicken.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlechicken.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlechristmastree.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlechristmastree.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlechristmastree.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlechristmastree.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlecow.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlecow.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlecow.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlecow.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlecrab.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlecrab.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlecrab.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlecrab.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googledog.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googledog.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googledog.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googledog.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googledove.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googledove.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googledove.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googledove.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googleduck.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googleduck.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googleduck.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googleduck.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googleeagle.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googleeagle.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googleeagle.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googleeagle.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlefire.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlefire.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlefire.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlefire.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlefox.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlefox.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlefox.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlefox.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googleghost.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googleghost.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googleghost.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googleghost.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlegift.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlegift.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlegift.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlegift.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlegoat.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlegoat.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlegoat.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlegoat.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlegun.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlegun.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlegun.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlegun.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googleicecream.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googleicecream.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googleicecream.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googleicecream.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlekoala.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlekoala.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlekoala.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlekoala.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlelion.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlelion.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlelion.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlelion.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlemouse.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlemouse.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlemouse.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlemouse.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlemuscleL.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlemuscleL.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlemuscleL.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlemuscleL.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlemuscleR.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlemuscleR.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlemuscleR.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlemuscleR.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googleoctopus.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googleoctopus.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googleoctopus.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googleoctopus.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlepanda.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlepanda.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlepanda.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlepanda.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlepenguin.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlepenguin.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlepenguin.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlepenguin.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlepig.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlepig.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlepig.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlepig.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlepizza.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlepizza.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlepizza.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlepizza.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlerabbit.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlerabbit.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlerabbit.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlerabbit.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlerat.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlerat.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlerat.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlerat.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googleredheart.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googleredheart.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googleredheart.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googleredheart.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlescorpion.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlescorpion.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlescorpion.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlescorpion.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlesheep.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlesheep.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlesheep.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlesheep.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlesnail.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlesnail.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlesnail.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlesnail.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlesnake.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlesnake.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlesnake.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlesnake.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlesquirrel.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlesquirrel.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlesquirrel.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlesquirrel.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googleturtle.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googleturtle.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googleturtle.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googleturtle.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlewhale.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlewhale.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/googlewhale.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/googlewhale.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/greentick.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/greentick.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/greentick.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/greentick.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/jakeblob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/jakeblob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/jakeblob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/jakeblob.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/kirbyblob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/kirbyblob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/kirbyblob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/kirbyblob.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/nellyblob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/nellyblob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/nellyblob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/nellyblob.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/nikoblob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/nikoblob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/nikoblob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/nikoblob.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/notlikeblob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/notlikeblob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/notlikeblob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/notlikeblob.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/pandablob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/pandablob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/pandablob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/pandablob.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/photoblob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/photoblob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/photoblob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/photoblob.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/pikablob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/pikablob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/pikablob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/pikablob.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/pusheenblob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/pusheenblob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/pusheenblob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/pusheenblob.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/rainblob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/rainblob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/rainblob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/rainblob.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/redtick.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/redtick.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/redtick.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/redtick.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/reindeerblob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/reindeerblob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/reindeerblob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/reindeerblob.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/rickblob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/rickblob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/rickblob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/rickblob.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/superblob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/superblob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/superblob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/superblob.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/thinkingwithblobs.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/thinkingwithblobs.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/thinkingwithblobs.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/thinkingwithblobs.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/wolfiriblob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/wolfiriblob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/wolfiriblob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/wolfiriblob.png diff --git a/SnapX.Core/ScreenCapture/Stickers/BlobEmoji/wumpusblob.png b/SnapX.Core/SharpCapture/Stickers/BlobEmoji/wumpusblob.png similarity index 100% rename from SnapX.Core/ScreenCapture/Stickers/BlobEmoji/wumpusblob.png rename to SnapX.Core/SharpCapture/Stickers/BlobEmoji/wumpusblob.png diff --git a/SnapX.Core/SnapX.Core.csproj b/SnapX.Core/SnapX.Core.csproj index 078bf2369..776f18cab 100644 --- a/SnapX.Core/SnapX.Core.csproj +++ b/SnapX.Core/SnapX.Core.csproj @@ -123,7 +123,7 @@ - + From 51692c7929b3269c8a37855bdbb78130aa15e0a1 Mon Sep 17 00:00:00 2001 From: Brycen G Date: Tue, 8 Jul 2025 08:37:57 -0400 Subject: [PATCH 02/31] refactor: move ViewModels to SnapX.CommonUI --- README.md | 2 +- SnapX.Avalonia/App.axaml.cs | 180 +----------------- SnapX.Avalonia/OSTray.cs | 163 ++++++++++++++++ SnapX.Avalonia/ViewLocator.cs | 1 + .../ViewModels/HomePageViewModel.cs | 18 +- SnapX.Avalonia/ViewModels/MainViewModel.cs | 5 +- SnapX.Avalonia/Views/HomePageView.axaml | 5 +- SnapX.Avalonia/Views/HomePageView.axaml.cs | 2 +- SnapX.Avalonia/Views/MainView.axaml.cs | 2 +- SnapX.Avalonia/Views/OCR.axaml | 2 +- SnapX.Avalonia/Views/OCR.axaml.cs | 2 +- .../Views/RegionSelectorWindow.axaml | 2 +- .../Views/RegionSelectorWindow.axaml.cs | 2 +- .../Models/ListItemTemplate.cs | 2 +- .../Models/ListTaskTemplate.cs | 2 +- SnapX.CommonUI/SnapX.CommonUI.csproj | 1 + SnapX.CommonUI/TaskThumbnailView.cs | 2 +- .../ViewModels/AboutWindowViewModel.cs | 7 +- .../ViewModels/AvaloniaChangelog.cs | 2 +- .../ViewModels/ChangelogViewModel.cs | 7 +- .../ViewModels/OCRViewModel.cs | 2 +- .../ViewModels/RegionSelectorViewModel.cs | 2 +- .../ViewModels/SettingsHomePageViewVM.cs | 2 +- .../ViewModels/SettingsMainViewVM.cs | 17 +- .../ViewModels/ViewModelBase.cs | 2 +- SnapX.Core/Job/TaskMetadata.cs | 2 +- SnapX.Core/Models/SavedConfiguration.cs | 22 --- SnapX.Core/SettingManager.cs | 88 --------- SnapX.Core/SnapX.cs | 2 +- SnapX.Core/SnapXResources.cs | 2 +- 30 files changed, 213 insertions(+), 337 deletions(-) create mode 100644 SnapX.Avalonia/OSTray.cs rename {SnapX.Avalonia => SnapX.CommonUI}/Models/ListItemTemplate.cs (68%) rename {SnapX.Avalonia => SnapX.CommonUI}/Models/ListTaskTemplate.cs (74%) rename {SnapX.Avalonia => SnapX.CommonUI}/ViewModels/AboutWindowViewModel.cs (96%) rename {SnapX.Avalonia => SnapX.CommonUI}/ViewModels/AvaloniaChangelog.cs (89%) rename {SnapX.Avalonia => SnapX.CommonUI}/ViewModels/ChangelogViewModel.cs (85%) rename {SnapX.Avalonia => SnapX.CommonUI}/ViewModels/OCRViewModel.cs (98%) rename {SnapX.Avalonia => SnapX.CommonUI}/ViewModels/RegionSelectorViewModel.cs (81%) rename {SnapX.Avalonia => SnapX.CommonUI}/ViewModels/SettingsHomePageViewVM.cs (61%) rename {SnapX.Avalonia => SnapX.CommonUI}/ViewModels/SettingsMainViewVM.cs (65%) rename {SnapX.Avalonia => SnapX.CommonUI}/ViewModels/ViewModelBase.cs (72%) delete mode 100644 SnapX.Core/Models/SavedConfiguration.cs diff --git a/README.md b/README.md index aa4ed3d3a..ced257c55 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ - Keeps compatibility with the custom uploader configuration format (.sxcu) - As a user, you do **NOT** need to have .NET installed. Whether you're on Linux, Windows, or macOS. -What does this all mean? It means you'll be able to have a more **performant**, **reliable**, and *modern* application. +What does this all mean? You'll have an app that **flies**, is **reliable**, and looks **sleek**. You will *not* receive any support from the ShareX project for this software. \ If you have any issues with this project, please **open an issue** in this repository. diff --git a/SnapX.Avalonia/App.axaml.cs b/SnapX.Avalonia/App.axaml.cs index e5c14717e..76d35e934 100644 --- a/SnapX.Avalonia/App.axaml.cs +++ b/SnapX.Avalonia/App.axaml.cs @@ -5,11 +5,8 @@ using Avalonia.Layout; using Avalonia.Markup.Xaml; using Avalonia.Media; -using Avalonia.Media.Imaging; -using Avalonia.Platform; using Avalonia.Styling; using CommunityToolkit.Mvvm.DependencyInjection; -using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Messaging; using FluentAvalonia.UI.Windowing; using Microsoft.Extensions.DependencyInjection; @@ -18,9 +15,8 @@ using SnapX.Avalonia.Views; using SnapX.Avalonia.Views.Settings; using SnapX.Avalonia.Views.Settings.Views; +using SnapX.CommonUI.ViewModels; using SnapX.Core; -using SnapX.Core.Capture; -using SnapX.Core.Job; using SnapX.Core.Utils; using SnapX.Core.Utils.Native; @@ -215,7 +211,7 @@ private void OnReportErrorClicked() Console.WriteLine("Report Error button clicked. No action yet. If you have telemetry enabled, (it is by default) it will have already been sent to Sentry."); } - private void Shutdown() + public static void Shutdown() { try { @@ -253,7 +249,7 @@ public override void OnFrameworkInitializationCompleted() DebugHelper.WriteLine("Received Shutdown from Avalonia"); if (sigintReceived) return; sigintReceived = true; - SnapX.shutdown(); + Shutdown(); // desktop.Shutdown(); }; @@ -264,22 +260,9 @@ public override void OnFrameworkInitializationCompleted() if (sigintReceived) return; ea.Cancel = true; sigintReceived = true; - SnapX.shutdown(); + Shutdown(); desktop.Shutdown(); }; - // AppDomain.CurrentDomain.ProcessExit += (o, _) => - // { - // if (!sigintReceived) - // { - // sigintReceived = true; - // DebugHelper.WriteLine("Received SIGTERM"); - // SnapX.shutdown(); - // } - // else - // { - // DebugHelper.WriteLine("Received SIGTERM, ignoring it because already processed SIGINT"); - // } - // }; var errorStarting = false; // DebugHelper.Logger.Debug($"Avalonia Args: {desktop.Args}"); try @@ -299,97 +282,6 @@ public override void OnFrameworkInitializationCompleted() if (errorStarting) return; DebugHelper.WriteLine("Internal Startup time: {0} ms", SnapX.getStartupTime()); - var logoBitmap = new Bitmap(AssetLoader.Open(new Uri("avares://snapx-ui/SnapX_Logo.png"))); - var trayIcon = new TrayIcon - { - Icon = new WindowIcon(logoBitmap), - ToolTipText = Core.SnapX.AppName, - Command = OpenSnapXCommand - }; - - var menu = new NativeMenu(); - menu.Opening += NativeMenu_OnOpening; - menu.NeedsUpdate += NativeMenu_OnNeedsUpdate; - - var about = new NativeMenuItem(TrayTitle) - { - Icon = logoBitmap, - ToolTip = Lang.AboutSnapX - }; - about.Click += NativeMenuItem_SnapX_OnClick; - menu.Items.Add(about); - menu.Items.Add(new NativeMenuItemSeparator()); - - var capture = new NativeMenuItem("Capture") { Menu = new NativeMenu() }; - var full = new NativeMenuItem(Lang.UI_Capture_Fullscreen); - full.Click += NativeMenuItem_Capture_Fullscreen_OnClick; - capture.Menu.Items.Add(full); - - var windowPicker = new NativeMenuItem(Lang.UI_Dropdown_Window) - { - Menu = new NativeMenu - { - new NativeMenuItem("SnapX UI") { Icon = logoBitmap }, - new NativeMenuItem("Marvel Rivals") { Icon = logoBitmap }, - new NativeMenuItem("Man of Steel (2013)") { Icon = logoBitmap } - } - }; - capture.Menu.Items.Add(windowPicker); - - var monitorPicker = new NativeMenuItem(Lang.UI_Dropdown_Monitor) { Menu = [] }; - monitorPicker.Menu.NeedsUpdate += NativeMenu_OnNeedsUpdate; - capture.Menu.Items.Add(monitorPicker); - - capture.Menu.Items.Add(new NativeMenuItem("Region")); - capture.Menu.Items.Add(new NativeMenuItem("Region (Light)")); - capture.Menu.Items.Add(new NativeMenuItem("Region (Transparent)")); - menu.Items.Add(capture); - - menu.Items.Add(new NativeMenuItem("Upload") - { - Menu = new NativeMenu - { - new NativeMenuItem("Upload File..."), - new NativeMenuItem("Upload Folder..."), - new NativeMenuItem("Upload from clipboard..."), - new NativeMenuItem("Upload text..."), - new NativeMenuItem("Drag and drop upload..."), - new NativeMenuItem("Shorten URL..."), - new NativeMenuItem("Tweet message...") - } - }); - var captureFullscreenMenuItem = new NativeMenuItem("Capture entire screen"); - captureFullscreenMenuItem.Click += NativeMenuItem_Capture_Fullscreen_OnClick; - var captureActiveWindowMenuItem = new NativeMenuItem("Capture active window"); - captureActiveWindowMenuItem.Click += NativeMenuItem_Workflows_CaptureActiveWindow_OnClick; - var captureActiveScreenMenuItem = new NativeMenuItem("Capture active screen"); - captureActiveScreenMenuItem.Click += NativeMenuItem_Workflows_CaptureActiveScreen_OnClick; - var workflows = new NativeMenuItem("Workflows") - { - Menu = - [ - captureFullscreenMenuItem, - captureActiveScreenMenuItem, - captureActiveWindowMenuItem, - ] - }; - - menu.Items.Add(workflows); - - menu.Items.Add(new NativeMenuItemSeparator()); - - var open = new NativeMenuItem("Open"); - open.Command = OpenSnapXCommand; - menu.Items.Add(open); - - var quit = new NativeMenuItem("Quit"); - quit.Click += NativeMenuItem_Quit_OnClick; - menu.Items.Add(quit); - - trayIcon.Menu = menu; - - TrayIcon.SetIcons(Current, [trayIcon]); - if (SnapX.isSilent()) return; if (SnapX.GetCLIManager().IsCommandExist("video")) { @@ -452,6 +344,10 @@ public static void CreateAboutWindowStatic() aboutWindow.Show(); } } + public static void NativeMenuAboutSnapXClick(object? Sender, EventArgs E) + { + CreateAboutWindowStatic(); + } public static void CreateSettingsWindowStatic() { var settingsWindow = Design.IsDesignMode @@ -471,12 +367,6 @@ public static void CreateSettingsWindowStatic() } } - - private void NativeMenuAboutSnapXClick(object? Sender, EventArgs E) - { - CreateAboutWindowStatic(); - } - public static void ConfigureServices(IServiceCollection services) { services.AddLogging(loggingBuilder => @@ -499,58 +389,4 @@ public static void ConfigureServices(IServiceCollection services) services.AddSingleton(WeakReferenceMessenger.Default); } - - private void NativeMenuItem_Quit_OnClick(object? Sender, EventArgs E) - { - Shutdown(); - } - - private void NativeMenuItem_SnapX_OnClick(object? Sender, EventArgs E) - { - NativeMenuAboutSnapXClick(Sender, E); - } - - private void NativeMenuItem_Capture_Fullscreen_OnClick(object? Sender, EventArgs E) - { - TaskHelpers.GetScreenshot().CaptureFullscreen(); - } - - private void NativeMenuItem_Workflows_CaptureActiveScreen_OnClick(object? Sender, EventArgs E) - { - new CaptureActiveMonitor().Capture(TaskSettings.GetDefaultTaskSettings()); - } - - private void NativeMenuItem_Workflows_CaptureActiveWindow_OnClick(object? Sender, EventArgs E) - { - new CaptureActiveWindow().Capture(TaskSettings.GetDefaultTaskSettings()); - } - - private void NativeMenuItem_Open_OnClick(object? Sender, EventArgs E) - { - if (!MyMainWindow?.IsLoaded ?? false) - { - var vm = Ioc.Default.GetRequiredService(); - MyMainWindow = new MainWindow(vm); - MyMainWindow.Show(); - } - - if (!MyMainWindow?.IsVisible ?? true) MyMainWindow?.Show(); - MyMainWindow?.Focus(); - MyMainWindow?.Activate(); - } - - [RelayCommand] - private void OpenSnapX() - { - NativeMenuItem_Open_OnClick(this, EventArgs.Empty); - } - private void NativeMenu_OnNeedsUpdate(object? Sender, EventArgs E) - { - DebugHelper.WriteLine("NativeMenu_OnNeedsUpdate"); - } - - private void NativeMenu_OnOpening(object? Sender, EventArgs E) - { - DebugHelper.WriteLine("NativeMenu_OnOpening"); - } } diff --git a/SnapX.Avalonia/OSTray.cs b/SnapX.Avalonia/OSTray.cs new file mode 100644 index 000000000..aa8f09113 --- /dev/null +++ b/SnapX.Avalonia/OSTray.cs @@ -0,0 +1,163 @@ +using Avalonia.Controls; +using Avalonia.Media.Imaging; +using Avalonia.Platform; +using CommunityToolkit.Mvvm.DependencyInjection; +using CommunityToolkit.Mvvm.Input; +using Serilog; +using SnapX.Avalonia.ViewModels; +using SnapX.Avalonia.Views; +using SnapX.Core.SharpCapture; +using SnapX.Core.Job; +using SnapX.Core.Utils; + +namespace SnapX.Avalonia; + +public partial class OSTray(App Current, ILogger Logger) +{ + public void display() + { + var logoBitmap = new Bitmap(AssetLoader.Open(new Uri("avares://snapx-ui/SnapX_Logo.png"))); + var trayIcon = new TrayIcon + { + Icon = new WindowIcon(logoBitmap), + ToolTipText = Core.SnapX.AppName, + Command = OpenSnapXCommand + }; + + var menu = new NativeMenu(); + menu.Opening += NativeMenu_OnOpening; + menu.NeedsUpdate += NativeMenu_OnNeedsUpdate; + + var about = new NativeMenuItem(TrayTitle) + { + Icon = logoBitmap, + ToolTip = Lang.AboutSnapX + }; + about.Click += NativeMenuItem_SnapX_OnClick; + menu.Items.Add(about); + menu.Items.Add(new NativeMenuItemSeparator()); + + var capture = new NativeMenuItem("Capture") { Menu = new NativeMenu() }; + var full = new NativeMenuItem(Lang.UI_Capture_Fullscreen); + full.Click += NativeMenuItem_Capture_Fullscreen_OnClick; + capture.Menu.Items.Add(full); + + var windowPicker = new NativeMenuItem(Lang.UI_Dropdown_Window) + { + Menu = new NativeMenu + { + new NativeMenuItem("SnapX UI") { Icon = logoBitmap }, + new NativeMenuItem("Marvel Rivals") { Icon = logoBitmap }, + new NativeMenuItem("Man of Steel (2013)") { Icon = logoBitmap } + } + }; + capture.Menu.Items.Add(windowPicker); + + var monitorPicker = new NativeMenuItem(Lang.UI_Dropdown_Monitor) { Menu = [] }; + monitorPicker.Menu.NeedsUpdate += NativeMenu_OnNeedsUpdate; + capture.Menu.Items.Add(monitorPicker); + + capture.Menu.Items.Add(new NativeMenuItem("Region")); + capture.Menu.Items.Add(new NativeMenuItem("Region (Light)")); + capture.Menu.Items.Add(new NativeMenuItem("Region (Transparent)")); + menu.Items.Add(capture); + + menu.Items.Add(new NativeMenuItem("Upload") + { + Menu = new NativeMenu + { + new NativeMenuItem("Upload File..."), + new NativeMenuItem("Upload Folder..."), + new NativeMenuItem("Upload from clipboard..."), + new NativeMenuItem("Upload text..."), + new NativeMenuItem("Drag and drop upload..."), + new NativeMenuItem("Shorten URL..."), + new NativeMenuItem("Tweet message...") + } + }); + var captureFullscreenMenuItem = new NativeMenuItem("Capture entire screen"); + captureFullscreenMenuItem.Click += NativeMenuItem_Capture_Fullscreen_OnClick; + var captureActiveWindowMenuItem = new NativeMenuItem("Capture active window"); + captureActiveWindowMenuItem.Click += NativeMenuItem_Workflows_CaptureActiveWindow_OnClick; + var captureActiveScreenMenuItem = new NativeMenuItem("Capture active screen"); + captureActiveScreenMenuItem.Click += NativeMenuItem_Workflows_CaptureActiveScreen_OnClick; + var workflows = new NativeMenuItem("Workflows") + { + Menu = + [ + captureFullscreenMenuItem, + captureActiveScreenMenuItem, + captureActiveWindowMenuItem, + ] + }; + + menu.Items.Add(workflows); + + menu.Items.Add(new NativeMenuItemSeparator()); + + var open = new NativeMenuItem("Open"); + open.Command = OpenSnapXCommand; + menu.Items.Add(open); + + var quit = new NativeMenuItem("Quit"); + quit.Click += NativeMenuItem_Quit_OnClick; + menu.Items.Add(quit); + + trayIcon.Menu = menu; + + TrayIcon.SetIcons(Current, [trayIcon]); + } + private void NativeMenuItem_Quit_OnClick(object? Sender, EventArgs E) + { + App.Shutdown(); + } + private void NativeMenuItem_SnapX_OnClick(object? Sender, EventArgs E) + { + App.NativeMenuAboutSnapXClick(Sender, E); + } + + private void NativeMenuItem_Capture_Fullscreen_OnClick(object? Sender, EventArgs E) + { + TaskHelpers.GetScreenshot().CaptureFullscreen(); + } + + private void NativeMenuItem_Workflows_CaptureActiveScreen_OnClick(object? Sender, EventArgs E) + { + new CaptureActiveMonitor().CaptureAsync(TaskSettings.GetDefaultTaskSettings()); + } + + private void NativeMenuItem_Workflows_CaptureActiveWindow_OnClick(object? Sender, EventArgs E) + { + new CaptureActiveWindow().Capture(TaskSettings.GetDefaultTaskSettings()); + } + + private void NativeMenuItem_Open_OnClick(object? Sender, EventArgs E) + { + var MyMainWindow = App.MyMainWindow; + if (!MyMainWindow?.IsLoaded ?? false) + { + var vm = Ioc.Default.GetRequiredService(); + MyMainWindow = new MainWindow(vm); + MyMainWindow.Show(); + } + + if (!MyMainWindow?.IsVisible ?? true) MyMainWindow?.Show(); + MyMainWindow?.Focus(); + MyMainWindow?.Activate(); + } + + [RelayCommand] + private void OpenSnapX() + { + NativeMenuItem_Open_OnClick(this, EventArgs.Empty); + } + private void NativeMenu_OnNeedsUpdate(object? Sender, EventArgs E) + { + Logger.Information("NativeMenu_OnNeedsUpdate"); + } + + private void NativeMenu_OnOpening(object? Sender, EventArgs E) + { + Logger.Information("NativeMenu_OnOpening"); + } +} diff --git a/SnapX.Avalonia/ViewLocator.cs b/SnapX.Avalonia/ViewLocator.cs index 0bb7eb282..77cd51482 100644 --- a/SnapX.Avalonia/ViewLocator.cs +++ b/SnapX.Avalonia/ViewLocator.cs @@ -7,6 +7,7 @@ using SnapX.Avalonia.Views; using SnapX.Avalonia.Views.Settings; using SnapX.Avalonia.Views.Settings.Views; +using SnapX.CommonUI.ViewModels; namespace SnapX.Avalonia; diff --git a/SnapX.Avalonia/ViewModels/HomePageViewModel.cs b/SnapX.Avalonia/ViewModels/HomePageViewModel.cs index a2d4214fc..7adc614e3 100644 --- a/SnapX.Avalonia/ViewModels/HomePageViewModel.cs +++ b/SnapX.Avalonia/ViewModels/HomePageViewModel.cs @@ -4,8 +4,9 @@ using Avalonia.Input; using Avalonia.Threading; using CommunityToolkit.Mvvm.Input; -using SnapX.Avalonia.Models; using SnapX.Avalonia.Views; +using SnapX.CommonUI.Models; +using SnapX.CommonUI.ViewModels; using SnapX.Core; using SnapX.Core.Job; using SnapX.Core.Upload; @@ -208,20 +209,17 @@ public async Task RefreshTasks() List newDesiredTasks; // Check cache first - if (DateTime.Now - _lastCacheTime < _cacheDuration && _cachedTasks != null) + if (DateTime.Now - _lastCacheTime < _cacheDuration) { newDesiredTasks = _cachedTasks; } else { - newDesiredTasks = await Task.Run(async () => - { - var historyItems = await TaskManager.History.GetHistoryItemsAsync(30_000).ConfigureAwait(false); - return historyItems.AsParallel() - .OrderByDescending(task => task.Id) - .Select(task => new ListTaskTemplate(typeofVM, task)) - .ToList(); - }).ConfigureAwait(false); + var historyItems = await TaskManager.History.GetHistoryItemsAsync(30_000).ConfigureAwait(false); + newDesiredTasks = historyItems + .OrderByDescending(task => task.Id) + .Select(task => new ListTaskTemplate(typeofVM, task)) + .ToList(); // Update cache _cachedTasks = newDesiredTasks; diff --git a/SnapX.Avalonia/ViewModels/MainViewModel.cs b/SnapX.Avalonia/ViewModels/MainViewModel.cs index 65f571d07..5a06bbd52 100644 --- a/SnapX.Avalonia/ViewModels/MainViewModel.cs +++ b/SnapX.Avalonia/ViewModels/MainViewModel.cs @@ -4,7 +4,8 @@ using CommunityToolkit.Mvvm.DependencyInjection; using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Messaging; -using SnapX.Avalonia.Models; +using SnapX.CommonUI.Models; +using SnapX.CommonUI.ViewModels; namespace SnapX.Avalonia.ViewModels; @@ -37,11 +38,9 @@ public MainViewModel() : this(new WeakReferenceMessenger()) { } partial void OnSelectedListItemChanged(ListItemTemplate? value) { if (value is null) return; -#pragma warning disable IL2072 // The code works, leave me alone var vm = Design.IsDesignMode ? Activator.CreateInstance(value.ModelType) : Ioc.Default.GetService(value.ModelType); -#pragma warning restore IL2072 if (vm is not ViewModelBase vmb) return; diff --git a/SnapX.Avalonia/Views/HomePageView.axaml b/SnapX.Avalonia/Views/HomePageView.axaml index d716d5883..bdc9aefdc 100644 --- a/SnapX.Avalonia/Views/HomePageView.axaml +++ b/SnapX.Avalonia/Views/HomePageView.axaml @@ -9,16 +9,13 @@ xmlns="https://github.com/avaloniaui" xmlns:asyncImageLoader="clr-namespace:AsyncImageLoader;assembly=AsyncImageLoader.Avalonia" xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" - xmlns:controls1="clr-namespace:SnapX.Avalonia.Views.Controls" xmlns:core="clr-namespace:SnapX.Core.Utils;assembly=SnapX.Core" xmlns:core1="clr-namespace:SnapX.Core;assembly=SnapX.Core" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:extensions="clr-namespace:SnapX.Avalonia.Extensions" - xmlns:fluent="clr-namespace:FluentIcons.Avalonia;assembly=FluentIcons.Avalonia" xmlns:fluent1="clr-namespace:FluentIcons.Avalonia.Fluent;assembly=FluentIcons.Avalonia.Fluent" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:models="clr-namespace:SnapX.Avalonia.Models" - xmlns:snapx="clr-namespace:SnapX.Core;assembly=SnapX.Core" + xmlns:models="clr-namespace:SnapX.CommonUI.Models;assembly=SnapX.CommonUI" xmlns:viewModels1="clr-namespace:SnapX.Avalonia.ViewModels" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> diff --git a/SnapX.Avalonia/Views/HomePageView.axaml.cs b/SnapX.Avalonia/Views/HomePageView.axaml.cs index 7e8d777b9..0a12988b9 100644 --- a/SnapX.Avalonia/Views/HomePageView.axaml.cs +++ b/SnapX.Avalonia/Views/HomePageView.axaml.cs @@ -2,9 +2,9 @@ using Avalonia.Controls; using Avalonia.Interactivity; using FluentAvalonia.UI.Controls; -using SnapX.Avalonia.Models; using SnapX.Avalonia.Services; using SnapX.Avalonia.ViewModels; +using SnapX.CommonUI.Models; using SnapX.Core; using SnapX.Core.Utils; using SnapX.Core.Utils.Miscellaneous; diff --git a/SnapX.Avalonia/Views/MainView.axaml.cs b/SnapX.Avalonia/Views/MainView.axaml.cs index df5806ca7..ebf22deeb 100644 --- a/SnapX.Avalonia/Views/MainView.axaml.cs +++ b/SnapX.Avalonia/Views/MainView.axaml.cs @@ -3,7 +3,7 @@ using Avalonia.LogicalTree; using CommunityToolkit.Mvvm.Input; using FluentAvalonia.UI.Controls; -using SnapX.Avalonia.ViewModels; +using SnapX.CommonUI.ViewModels; using SnapX.Core; using SnapX.Core.Job; using SnapX.Core.Upload; diff --git a/SnapX.Avalonia/Views/OCR.axaml b/SnapX.Avalonia/Views/OCR.axaml index 52faf3554..a5e676217 100644 --- a/SnapX.Avalonia/Views/OCR.axaml +++ b/SnapX.Avalonia/Views/OCR.axaml @@ -6,7 +6,7 @@ x:Class="SnapX.Avalonia.Views.OCR" x:DataType="viewModels:OCRViewModel" xmlns="https://github.com/avaloniaui" - xmlns:viewModels="clr-namespace:SnapX.Avalonia.ViewModels" + xmlns:viewModels="clr-namespace:SnapX.CommonUI.ViewModels;assembly=SnapX.CommonUI" xmlns:windowing="clr-namespace:FluentAvalonia.UI.Windowing;assembly=FluentAvalonia" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> diff --git a/SnapX.Avalonia/Views/OCR.axaml.cs b/SnapX.Avalonia/Views/OCR.axaml.cs index 3cd0d93ef..2ae007f6a 100644 --- a/SnapX.Avalonia/Views/OCR.axaml.cs +++ b/SnapX.Avalonia/Views/OCR.axaml.cs @@ -1,7 +1,7 @@ using Avalonia.Controls; using Avalonia.Interactivity; using FluentAvalonia.UI.Windowing; -using SnapX.Avalonia.ViewModels; +using SnapX.CommonUI.ViewModels; using SnapX.Core; using SnapX.Core.History; using SnapX.Core.Utils; diff --git a/SnapX.Avalonia/Views/RegionSelectorWindow.axaml b/SnapX.Avalonia/Views/RegionSelectorWindow.axaml index ea4390048..f00e9b865 100644 --- a/SnapX.Avalonia/Views/RegionSelectorWindow.axaml +++ b/SnapX.Avalonia/Views/RegionSelectorWindow.axaml @@ -24,7 +24,7 @@ xmlns="https://github.com/avaloniaui" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:viewModels="clr-namespace:SnapX.Avalonia.ViewModels" + xmlns:viewModels="clr-namespace:SnapX.CommonUI.ViewModels;assembly=SnapX.CommonUI" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> diff --git a/SnapX.Avalonia/Views/RegionSelectorWindow.axaml.cs b/SnapX.Avalonia/Views/RegionSelectorWindow.axaml.cs index e8a531142..3d4af1e29 100644 --- a/SnapX.Avalonia/Views/RegionSelectorWindow.axaml.cs +++ b/SnapX.Avalonia/Views/RegionSelectorWindow.axaml.cs @@ -8,7 +8,7 @@ using Avalonia.Threading; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Processing; -using SnapX.Avalonia.ViewModels; +using SnapX.CommonUI.ViewModels; using SnapX.Core; using SnapX.Core.Job; using SnapX.Core.Upload; diff --git a/SnapX.Avalonia/Models/ListItemTemplate.cs b/SnapX.CommonUI/Models/ListItemTemplate.cs similarity index 68% rename from SnapX.Avalonia/Models/ListItemTemplate.cs rename to SnapX.CommonUI/Models/ListItemTemplate.cs index e5052b228..886b05d28 100644 --- a/SnapX.Avalonia/Models/ListItemTemplate.cs +++ b/SnapX.CommonUI/Models/ListItemTemplate.cs @@ -1,3 +1,3 @@ -namespace SnapX.Avalonia.Models; +namespace SnapX.CommonUI.Models; public record ListItemTemplate(Type ModelType, string IconKey, string Label); diff --git a/SnapX.Avalonia/Models/ListTaskTemplate.cs b/SnapX.CommonUI/Models/ListTaskTemplate.cs similarity index 74% rename from SnapX.Avalonia/Models/ListTaskTemplate.cs rename to SnapX.CommonUI/Models/ListTaskTemplate.cs index e1c2fd307..73b2f7eff 100644 --- a/SnapX.Avalonia/Models/ListTaskTemplate.cs +++ b/SnapX.CommonUI/Models/ListTaskTemplate.cs @@ -1,5 +1,5 @@ using SnapX.Core.History; -namespace SnapX.Avalonia.Models; +namespace SnapX.CommonUI.Models; public record ListTaskTemplate(Type ModelType, HistoryItem task); diff --git a/SnapX.CommonUI/SnapX.CommonUI.csproj b/SnapX.CommonUI/SnapX.CommonUI.csproj index 9f2367792..4e84d305d 100644 --- a/SnapX.CommonUI/SnapX.CommonUI.csproj +++ b/SnapX.CommonUI/SnapX.CommonUI.csproj @@ -9,5 +9,6 @@ + diff --git a/SnapX.CommonUI/TaskThumbnailView.cs b/SnapX.CommonUI/TaskThumbnailView.cs index 2696445c1..af5bdc35d 100644 --- a/SnapX.CommonUI/TaskThumbnailView.cs +++ b/SnapX.CommonUI/TaskThumbnailView.cs @@ -57,7 +57,7 @@ private Image CreateThumbnail(string? filePath = null, Image? img = null) if (img != null) return ImageHelpers.ResizeImage(img, ThumbnailSize, false); if (string.IsNullOrWhiteSpace(filePath)) filePath = Task.Info.FileName; else if (File.Exists(filePath)) return ImageHelpers.ResizeImage(Image.Load(filePath), ThumbnailSize, true); - if (string.IsNullOrEmpty(filePath)) return null; // TODO: Embed error image + if (string.IsNullOrEmpty(filePath)) return Image.Load([]); // TODO: Embed error image var icon = Methods.GetJumboFileIcon(filePath, false); return ImageHelpers.ResizeImage(icon, ThumbnailSize, false, true); } diff --git a/SnapX.Avalonia/ViewModels/AboutWindowViewModel.cs b/SnapX.CommonUI/ViewModels/AboutWindowViewModel.cs similarity index 96% rename from SnapX.Avalonia/ViewModels/AboutWindowViewModel.cs rename to SnapX.CommonUI/ViewModels/AboutWindowViewModel.cs index aa1e9c0d7..559b1bfc0 100644 --- a/SnapX.Avalonia/ViewModels/AboutWindowViewModel.cs +++ b/SnapX.CommonUI/ViewModels/AboutWindowViewModel.cs @@ -1,11 +1,10 @@ using System.Diagnostics.CodeAnalysis; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; -using SnapX.CommonUI; using SnapX.Core.Utils; using SnapX.Core.Utils.Miscellaneous; -namespace SnapX.Avalonia.ViewModels; +namespace SnapX.CommonUI.ViewModels; public partial class AboutWindowViewModel : ViewModelBase { @@ -18,9 +17,7 @@ public partial class AboutWindowViewModel : ViewModelBase RelayCommand] private Task InitDataAsync() { - var combinedLoadedAssemblies = AppDomain.CurrentDomain.GetAssemblies() - .Concat(App.SnapX.GetAssemblies()) - .Distinct(); + var combinedLoadedAssemblies = AppDomain.CurrentDomain.GetAssemblies(); LoadedAssemblies = string.Join(Environment.NewLine, combinedLoadedAssemblies .Where(a => a.GetName().Name != null) .Where(a => diff --git a/SnapX.Avalonia/ViewModels/AvaloniaChangelog.cs b/SnapX.CommonUI/ViewModels/AvaloniaChangelog.cs similarity index 89% rename from SnapX.Avalonia/ViewModels/AvaloniaChangelog.cs rename to SnapX.CommonUI/ViewModels/AvaloniaChangelog.cs index 19360251d..92c32c2c5 100644 --- a/SnapX.Avalonia/ViewModels/AvaloniaChangelog.cs +++ b/SnapX.CommonUI/ViewModels/AvaloniaChangelog.cs @@ -1,4 +1,4 @@ -namespace SnapX.Avalonia; +namespace SnapX.CommonUI.ViewModels; public class AvaloniaChangelog : SnapX.CommonUI.Changelog { diff --git a/SnapX.Avalonia/ViewModels/ChangelogViewModel.cs b/SnapX.CommonUI/ViewModels/ChangelogViewModel.cs similarity index 85% rename from SnapX.Avalonia/ViewModels/ChangelogViewModel.cs rename to SnapX.CommonUI/ViewModels/ChangelogViewModel.cs index 633d13885..0526cab1e 100644 --- a/SnapX.Avalonia/ViewModels/ChangelogViewModel.cs +++ b/SnapX.CommonUI/ViewModels/ChangelogViewModel.cs @@ -1,14 +1,13 @@ -using Avalonia.Collections; +using System.Collections.ObjectModel; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; -using SnapX.CommonUI; using SnapX.Core.Utils; -namespace SnapX.Avalonia.ViewModels; +namespace SnapX.CommonUI.ViewModels; public partial class ChangelogViewModel : ViewModelBase { - public AvaloniaList Versions { get; } = []; + public ObservableCollection Versions { get; } = []; [ObservableProperty] public Changelog.ChangelogVersion selectedChangelogVersion = new(); diff --git a/SnapX.Avalonia/ViewModels/OCRViewModel.cs b/SnapX.CommonUI/ViewModels/OCRViewModel.cs similarity index 98% rename from SnapX.Avalonia/ViewModels/OCRViewModel.cs rename to SnapX.CommonUI/ViewModels/OCRViewModel.cs index de9742e19..f014cd0de 100644 --- a/SnapX.Avalonia/ViewModels/OCRViewModel.cs +++ b/SnapX.CommonUI/ViewModels/OCRViewModel.cs @@ -5,7 +5,7 @@ using SnapX.Core.Utils; using Image = SixLabors.ImageSharp.Image; -namespace SnapX.Avalonia.ViewModels; +namespace SnapX.CommonUI.ViewModels; public partial class OCRViewModel : ViewModelBase { diff --git a/SnapX.Avalonia/ViewModels/RegionSelectorViewModel.cs b/SnapX.CommonUI/ViewModels/RegionSelectorViewModel.cs similarity index 81% rename from SnapX.Avalonia/ViewModels/RegionSelectorViewModel.cs rename to SnapX.CommonUI/ViewModels/RegionSelectorViewModel.cs index cc8ec1f88..a2b91578b 100644 --- a/SnapX.Avalonia/ViewModels/RegionSelectorViewModel.cs +++ b/SnapX.CommonUI/ViewModels/RegionSelectorViewModel.cs @@ -1,4 +1,4 @@ -namespace SnapX.Avalonia.ViewModels; +namespace SnapX.CommonUI.ViewModels; public partial class RegionSelectorViewModel : ViewModelBase { private int Width; diff --git a/SnapX.Avalonia/ViewModels/SettingsHomePageViewVM.cs b/SnapX.CommonUI/ViewModels/SettingsHomePageViewVM.cs similarity index 61% rename from SnapX.Avalonia/ViewModels/SettingsHomePageViewVM.cs rename to SnapX.CommonUI/ViewModels/SettingsHomePageViewVM.cs index e6823e461..2b22bc0e2 100644 --- a/SnapX.Avalonia/ViewModels/SettingsHomePageViewVM.cs +++ b/SnapX.CommonUI/ViewModels/SettingsHomePageViewVM.cs @@ -1,4 +1,4 @@ -namespace SnapX.Avalonia.ViewModels; +namespace SnapX.CommonUI.ViewModels; public class SettingsHomePageViewVM : ViewModelBase { diff --git a/SnapX.Avalonia/ViewModels/SettingsMainViewVM.cs b/SnapX.CommonUI/ViewModels/SettingsMainViewVM.cs similarity index 65% rename from SnapX.Avalonia/ViewModels/SettingsMainViewVM.cs rename to SnapX.CommonUI/ViewModels/SettingsMainViewVM.cs index 9745f5492..d1b82b018 100644 --- a/SnapX.Avalonia/ViewModels/SettingsMainViewVM.cs +++ b/SnapX.CommonUI/ViewModels/SettingsMainViewVM.cs @@ -1,10 +1,9 @@ -using Avalonia.Collections; -using Avalonia.Controls; +using System.Collections.ObjectModel; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.DependencyInjection; -using SnapX.Avalonia.Models; +using SnapX.CommonUI.Models; -namespace SnapX.Avalonia.ViewModels; +namespace SnapX.CommonUI.ViewModels; public partial class SettingsMainViewVM : ViewModelBase { @@ -15,23 +14,19 @@ public partial class SettingsMainViewVM : ViewModelBase private ViewModelBase _currentPage = new SettingsHomePageViewVM(); [ObservableProperty] private ListItemTemplate? _selectedListItem; - public AvaloniaList Items { get; } + public ObservableCollection Items { get; } public SettingsMainViewVM() { _currentPage = new SettingsHomePageViewVM(); - Items = new AvaloniaList(_templates); + Items = new ObservableCollection(_templates); SelectedListItem = Items.First(vm => vm.ModelType == typeof(SettingsHomePageViewVM)); } partial void OnSelectedListItemChanged(ListItemTemplate? value) { if (value is null) return; -#pragma warning disable IL2072 // The code works, leave me alone - var vm = Design.IsDesignMode - ? Activator.CreateInstance(value.ModelType) - : Ioc.Default.GetService(value.ModelType); -#pragma warning restore IL2072 + var vm = Ioc.Default.GetService(value.ModelType); if (vm is not ViewModelBase vmb) return; diff --git a/SnapX.Avalonia/ViewModels/ViewModelBase.cs b/SnapX.CommonUI/ViewModels/ViewModelBase.cs similarity index 72% rename from SnapX.Avalonia/ViewModels/ViewModelBase.cs rename to SnapX.CommonUI/ViewModels/ViewModelBase.cs index eafcb5e39..2790b058c 100644 --- a/SnapX.Avalonia/ViewModels/ViewModelBase.cs +++ b/SnapX.CommonUI/ViewModels/ViewModelBase.cs @@ -1,5 +1,5 @@ using CommunityToolkit.Mvvm.ComponentModel; -namespace SnapX.Avalonia.ViewModels; +namespace SnapX.CommonUI.ViewModels; public class ViewModelBase : ObservableObject; diff --git a/SnapX.Core/Job/TaskMetadata.cs b/SnapX.Core/Job/TaskMetadata.cs index 9570e031f..e683a3094 100644 --- a/SnapX.Core/Job/TaskMetadata.cs +++ b/SnapX.Core/Job/TaskMetadata.cs @@ -11,7 +11,7 @@ public class TaskMetadata : IDisposable { private const int WindowInfoMaxLength = 255; - public Image Image { get; set; } + public Image? Image { get; set; } private string? windowTitle; diff --git a/SnapX.Core/Models/SavedConfiguration.cs b/SnapX.Core/Models/SavedConfiguration.cs deleted file mode 100644 index 440ece770..000000000 --- a/SnapX.Core/Models/SavedConfiguration.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; - - -namespace SnapX.Core.Models; - -[Table("ApplicationConfig")] -public record SavedConfiguration -{ - [Key] - public int Id { get; set; } - - public string ConfigSection { get; set; } - - public string SettingKey { get; set; } - - public string SettingValue { get; set; } - - public string DataType { get; set; } - - public DateTime UpdatedAt { get; set; } -} diff --git a/SnapX.Core/SettingManager.cs b/SnapX.Core/SettingManager.cs index 8b1dd357e..2cccf0048 100644 --- a/SnapX.Core/SettingManager.cs +++ b/SnapX.Core/SettingManager.cs @@ -203,60 +203,6 @@ public static void LoadHotkeysConfig(bool fallbackSupport = true) HotkeysConfigBackwardCompatibilityTasks(); } - // private static void MigrateApplicationConfigJSONToSQLite() - // { - // try - // { - // DebugHelper.WriteLine($"JSON -> SQLite Migration: Migrating {ApplicationConfigFileName} at {ApplicationConfigFilePath}"); - // var json = File.ReadAllText(ApplicationConfigFilePath); - // var node = JsonNode.Parse(json)!.AsObject(); - // node.Remove("RecentTasks"); - // - // var nodeJSON = node.ToJsonString(); - // - // var root = JsonDocument.Parse(nodeJSON).RootElement; - // foreach (var property in root.EnumerateObject()) - // { - // var key = property.Name; - // var value = property.Value; - // - // switch (value.ValueKind) - // { - // case JsonValueKind.Object: - // FlattenAndInsert(value, key); - // break; - // - // case JsonValueKind.Array: - // var index = 0; - // foreach (var item in value.EnumerateArray()) - // { - // // Compose a "key:index" prefix for each item and recurse - // FlattenAndInsert(item, $"{key}:{index++}"); - // } - // - // break; - // - // case JsonValueKind.String: - // case JsonValueKind.Number: - // case JsonValueKind.True: - // case JsonValueKind.False: - // case JsonValueKind.Null: - // case JsonValueKind.Undefined: - // default: - // FlattenAndInsert(value, key); - // break; - // } - // } - // var migratedPath = ApplicationConfigFilePath + ".migrated"; - // var timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss"); - // migratedPath = ApplicationConfigFilePath + $"{timestamp}.migrated"; - // File.Move(ApplicationConfigFilePath, migratedPath); - // } - // catch (Exception ex) - // { - // DebugHelper.WriteException(ex); - // } - // } public static void SaveApplicationConfig() { if (SnapX.Sandbox) @@ -524,18 +470,6 @@ private static void UploadersConfigBackwardCompatibilityTasks() private static void HotkeysConfigBackwardCompatibilityTasks() { - - // if (Settings.IsUpgradeFrom("15.0.1")) - // { - // foreach (var taskSettings in HotkeysConfig.Hotkeys.Select(x => x.TaskSettings)) - // { - // if (tasktaskSettings.CaptureSettings != null) - // { - // // taskSettings.CaptureSettings.ScrollingCaptureOptions = new ScrollingCaptureOptions(); - // // taskSettings.CaptureSettings.FFmpegOptions.FixSources(); - // } - // } - // } } public static void Dispose() => theLaw.Dispose(); @@ -653,27 +587,5 @@ public static bool Import(string archivePath) return false; } - - // This method validates the setting before restoration to ensure it fits the defined type - private static bool IsValidValue(string value, string dataType) - { - if (string.IsNullOrWhiteSpace(value)) - return false; // Prevent null or empty values. - - switch (dataType) - { - case "int": - return int.TryParse(value, out _); - case "double": - return double.TryParse(value, out _); - case "bool": - return bool.TryParse(value, out _); - case "string": - return true; - default: - DebugHelper.WriteLine($"Unknown data type: {dataType}"); - return false; - } - } } diff --git a/SnapX.Core/SnapX.cs b/SnapX.Core/SnapX.cs index 5026bf877..06d45e997 100644 --- a/SnapX.Core/SnapX.cs +++ b/SnapX.Core/SnapX.cs @@ -710,7 +710,7 @@ private static void HandleExceptions() // Add the event handler for handling non-UI thread exceptions to the event AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; - AppDomain.CurrentDomain.ProcessExit += ((_, _) => CloseSequence()); + AppDomain.CurrentDomain.ProcessExit += (_, _) => CloseSequence(); } private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) => OnError((Exception)e.ExceptionObject); private static void OnError(Exception e) => DebugHelper.WriteException(e); diff --git a/SnapX.Core/SnapXResources.cs b/SnapX.Core/SnapXResources.cs index 39c0f87b4..144f5a51b 100644 --- a/SnapX.Core/SnapXResources.cs +++ b/SnapX.Core/SnapXResources.cs @@ -15,5 +15,5 @@ public static class SnapXResources public static OsInfo.GenericGraphicsInfo graphicsInfo => OsInfo.GetGenericGraphicsInfo(); public static string Dotnet => RuntimeInformation.FrameworkDescription; public static string fancyOsName => Helpers.GetOperatingSystemProductName(); - public static string? UserAgent => $"{SnapX.AppName}/{Helpers.GetApplicationVersion()} (+{Links.GitHub})"; + public static string UserAgent => $"{SnapX.AppName}/{Helpers.GetApplicationVersion()} (+{Links.GitHub})"; } From c3d41308e4d4069bf7021356a7e0c15c427fd39d Mon Sep 17 00:00:00 2001 From: Brycen G Date: Wed, 9 Jul 2025 18:10:50 -0400 Subject: [PATCH 03/31] refactor(build): use clean architecture --- build/Build.cs | 2 +- build/BuildConfig.cs | 8 ++++++-- build/CLI.cs | 4 +--- build/CommandRunner.cs | 2 +- build/DirectoryService.cs | 2 +- build/FS.cs | 4 ++-- build/IFileSystem.cs | 3 +++ build/Install.cs | 3 ++- build/Program.cs | 5 ++--- build/Tarball.cs | 2 +- build/Uninstall.cs | 2 +- build/build.csproj | 1 + 12 files changed, 22 insertions(+), 16 deletions(-) diff --git a/build/Build.cs b/build/Build.cs index 9b986b6d0..29cc2d14f 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -78,7 +78,7 @@ await FileSystem.FileWriteAllTextAsync(manifestFile, json.ToJsonString(new JsonS private Task HandleRustLibCopy(string rootDirectory, string outputDir) { const string rustLib = "libsnapxrust.dylib"; - var sourcePath = Path.Combine(rootDirectory, "SnapX.Core", "ScreenCapture", "Rust", "target", "release", rustLib); + var sourcePath = Path.Combine(rootDirectory, "SnapX.Core", "SharpCapture", "Rust", "target", "release", rustLib); if (!File.Exists(sourcePath)) return Task.CompletedTask; diff --git a/build/BuildConfig.cs b/build/BuildConfig.cs index 83b86b35b..60c772745 100644 --- a/build/BuildConfig.cs +++ b/build/BuildConfig.cs @@ -34,7 +34,7 @@ public string Docdir public string Icondir => Path.Join(Datadir, "icons", "hicolor"); public string Runtime { get; set; } = RuntimeInformation.RuntimeIdentifier; public string Metainfodir => Path.Join(Datadir, "metainfo"); - public string RootDirectory { get; } = Path.GetRelativePath(Directory.GetCurrentDirectory(), DirectoryService.FindRoot()); + public string RootDirectory { get; set; } = Path.GetRelativePath(Directory.GetCurrentDirectory(), DirectoryService.FindRoot()); public string PackagingDirectory => Path.Combine(RootDirectory, "packaging"); public string Tarballdir => Path.Combine(PackagingDirectory, "tarball"); public string Appdir => Path.Combine(PackagingDirectory, "AppDir"); @@ -80,7 +80,11 @@ public bool ShouldSkip(string stepName) public string[] Targets { get; init; } = []; public string[] SkippedStepsRaw { get; init; } = []; - public string OutputDir { get; init; } = "Output"; + public string OutputDir + { + get => field ??= Path.Combine(RootDirectory, "Output"); + set; + } public string Configuration { get; init; } = "Release"; public bool EnableWrapperScriptFallback { get; init; } public bool DisableWrapperScript { get; set; } = OperatingSystem.IsWindows(); diff --git a/build/CLI.cs b/build/CLI.cs index 0bf5b7c50..5235f841e 100644 --- a/build/CLI.cs +++ b/build/CLI.cs @@ -100,7 +100,6 @@ public async Task InvokeAsync(string[] args, Func handle { Description = "The directory to output builds artifacts to.", Arity = ArgumentArity.ExactlyOne, - DefaultValueFactory = _ => "Output" }; rootCommand.Options.Add(outputDirOption); @@ -163,7 +162,7 @@ public async Task InvokeAsync(string[] args, Func handle var config = new BuildConfig { Targets = parseResult.GetValue(targetsArgument) ?? [], - OutputDir = parseResult.GetValue(outputDirOption) ?? "Output", + OutputDir = parseResult.GetValue(outputDirOption)!, Configuration = parseResult.GetValue(configurationOption) ?? "Release", ExtraArgs = parseResult.GetValue(extraArgsOption) ?? "", SkippedStepsRaw = parseResult.GetValue(skipStepOption) ?? [], @@ -195,7 +194,6 @@ public async Task InvokeAsync(string[] args, Func handle if (prefix is not null) config.Prefix = prefix; if (libDir is not null) config.LibDir = libDir; if (docDir is not null) config.Docdir = docDir; - // Set skipped steps based on parsed options config.SetSkippedSteps(config.SkippedStepsRaw); diff --git a/build/CommandRunner.cs b/build/CommandRunner.cs index e9dca3e59..8730c8af4 100644 --- a/build/CommandRunner.cs +++ b/build/CommandRunner.cs @@ -16,7 +16,7 @@ public async Task InstallFile(string source, string destination, string permissi var directoryPath = Path.GetDirectoryName(destination); if (!string.IsNullOrEmpty(directoryPath) && !Directory.Exists(directoryPath) && !File.Exists(directoryPath)) { - DirectoryService.EnsureDirectoryExists(directoryPath); + new DirectoryService(Logger, this).EnsureDirectoryExists(directoryPath); } if (source.Contains("dSYM", StringComparison.InvariantCultureIgnoreCase)) { diff --git a/build/DirectoryService.cs b/build/DirectoryService.cs index 014fa7cc4..b0d954768 100644 --- a/build/DirectoryService.cs +++ b/build/DirectoryService.cs @@ -53,7 +53,7 @@ public static void TryDeleteMatchingFiles(string directoryPath, string[] searchP TryDeleteFile(file); } } - public static void EnsureDirectoryExists(string directory) + public void EnsureDirectoryExists(string directory) { if (Directory.Exists(directory)) return; try diff --git a/build/FS.cs b/build/FS.cs index c98b55545..1e3f8b7e0 100644 --- a/build/FS.cs +++ b/build/FS.cs @@ -1,6 +1,6 @@ namespace DefaultNamespace; -public class FS(IBuildLogger Logger, CommandRunner CommandRunner) : IFileSystem +public class FS(IBuildLogger Logger, ICommandRunner CommandRunner) : IFileSystem { public async Task TryDeleteFile(string path) { @@ -89,7 +89,7 @@ public async Task FileWriteAllTextAsync(string path, string contents) public Task EnsureDirectoryExistsAsync(string path) { - DirectoryService.EnsureDirectoryExists(path); + new DirectoryService(Logger, CommandRunner).EnsureDirectoryExists(path); return Task.CompletedTask; } } diff --git a/build/IFileSystem.cs b/build/IFileSystem.cs index 14650de91..e941a491f 100644 --- a/build/IFileSystem.cs +++ b/build/IFileSystem.cs @@ -4,6 +4,9 @@ public interface IFileSystem { void FileCopy(string sourceFileName, string destFileName, bool overwrite); void DirectoryDelete(string path, bool recursive); + Task TryDeleteMatchingFiles(string directory, string[] searchPatterns); + Task TryDeleteEmptyDir(string directory); + Task TryDeleteFile(string path); string[] DirectoryGetFiles(string path, string searchPattern, SearchOption searchOption); string[] DirectoryGetDirectories(string path, string searchPattern, SearchOption searchOption); Task FileReadAllTextAsync(string path); diff --git a/build/Install.cs b/build/Install.cs index f545508b2..2689aa0f6 100644 --- a/build/Install.cs +++ b/build/Install.cs @@ -1,6 +1,6 @@ namespace DefaultNamespace; -public class Install(IBuildLogger Logger, ICommandRunner CommandRunner, FS FileSystem, BuildConfig config) +public class Install(IBuildLogger Logger, ICommandRunner CommandRunner, IFileSystem FileSystem, BuildConfig config) { public async Task ProcessInstall() { @@ -13,6 +13,7 @@ public async Task ProcessInstall() private void LogInstallationPaths() { Logger.Information($"--- Installation Paths ---"); + Logger.Information($"Build Output: {config.OutputDir}"); Logger.Information($"Root directory: {config.RootDirectory}"); Logger.Information($"Destination Directory (DESTDIR): {config.DestDir}"); Logger.Information($"Prefix: {config.Prefix}"); diff --git a/build/Program.cs b/build/Program.cs index 5b2ae808a..916de18d1 100644 --- a/build/Program.cs +++ b/build/Program.cs @@ -8,9 +8,8 @@ namespace DefaultNamespace; internal class Program { - private static readonly ConsoleLogger logger = new(); - private static readonly CommandRunner commandRunner = new(logger); - internal static readonly DirectoryService directoryService = new(logger, commandRunner); + private static readonly IBuildLogger logger = new ConsoleLogger(); + private static readonly ICommandRunner commandRunner = new CommandRunner(logger); private static readonly FS fileSystem = new(logger, commandRunner); private async Task ExecuteAsync(BuildConfig config) diff --git a/build/Tarball.cs b/build/Tarball.cs index d9fd7419c..b236caec2 100644 --- a/build/Tarball.cs +++ b/build/Tarball.cs @@ -1,6 +1,6 @@ namespace DefaultNamespace; -public class Tarball(IBuildLogger Logger, ICommandRunner CommandRunner, FS FileSystem, BuildConfig config) +public class Tarball(IBuildLogger Logger, ICommandRunner CommandRunner, IFileSystem FileSystem, BuildConfig config) { public async Task ProcessTarball() { diff --git a/build/Uninstall.cs b/build/Uninstall.cs index 489278130..794065143 100644 --- a/build/Uninstall.cs +++ b/build/Uninstall.cs @@ -1,6 +1,6 @@ namespace DefaultNamespace; -public class Uninstall(IBuildLogger Logger, FS FileSystem, BuildConfig config) +public class Uninstall(IBuildLogger Logger, IFileSystem FileSystem, BuildConfig config) { private static readonly string[] libraryExtensions = ["*.so", "*.dylib", "*.dll"]; public async Task ProcessUninstall() diff --git a/build/build.csproj b/build/build.csproj index ff2246474..09f7528c3 100644 --- a/build/build.csproj +++ b/build/build.csproj @@ -5,6 +5,7 @@ Exe DefaultNamespace preview + Build.Tests From 7d9f217c23eedc3e165d29cf885a23266c0e350b Mon Sep 17 00:00:00 2001 From: Brycen G Date: Fri, 11 Jul 2025 19:47:58 -0400 Subject: [PATCH 04/31] fix(Avalonia): use events to alert callers of new logs instead of polling Switched the log viewer from a polling mechanism to an observable pattern. The previous approach's constant 50ms checks were inefficient and consumed unnecessary CPU cycles. This change eliminates that fixed delay and constant polling overhead, allowing new log entries to appear instantly as they're generated. --- SnapX.Avalonia/Views/LogViewer.axaml | 2 +- SnapX.Avalonia/Views/LogViewer.axaml.cs | 92 +++++++++++-------------- SnapX.Core/DebugHelper.cs | 7 +- SnapX.Core/SnapX.Core.csproj | 1 - 4 files changed, 45 insertions(+), 57 deletions(-) diff --git a/SnapX.Avalonia/Views/LogViewer.axaml b/SnapX.Avalonia/Views/LogViewer.axaml index 70bcf458d..af946522e 100644 --- a/SnapX.Avalonia/Views/LogViewer.axaml +++ b/SnapX.Avalonia/Views/LogViewer.axaml @@ -1,7 +1,7 @@ RefreshLogs(); } - private void AppWindow_OnLoaded(object? sender, RoutedEventArgs e) + private void AppWindow_OnLoaded(object? sender, EventArgs e) { - _scrollViewer = this.FindControl("ScrollViewer"); - _logTextBlock = this.FindControl("LogTextBlock"); - _lastDisplayedLogCount = 0; - _refreshTimer.Start(); + RefreshLogs(); + DebugHelper.observableSink.LogMessageReceived += (_, _) => RefreshLogs(); } private void AppWindow_OnClosed(object? sender, EventArgs e) { _lastDisplayedLogCount = 0; - _refreshTimer.Stop(); } private void Close_Click(object? sender, RoutedEventArgs e) => Close(); private void RefreshLogs() { - if (DebugHelper.LogEvents.Count() <= _lastDisplayedLogCount) return; - for (var i = _lastDisplayedLogCount; i < DebugHelper.LogEvents.Count(); i++) + _scrollViewer = this.FindControl("ScrollViewer"); + _logTextBlock = this.FindControl("LogTextBlock"); + var bufferedEvents = DebugHelper.observableSink.GetBufferedEvents(); + for (var i = _lastDisplayedLogCount; i < bufferedEvents.Count; i++) { - var logEvent = DebugHelper.LogEvents.ElementAt(i); + var logEvent = DebugHelper.observableSink.GetBufferedEvents().ElementAt(i); var timestamp = logEvent.Timestamp.ToString("hh:mm:ss"); var level = logEvent.Level.ToString().ToUpper(); if (level == "INFORMATION") level = "INFO"; @@ -64,7 +56,7 @@ private void RefreshLogs() _logTextBlock.Inlines!.Add(new Run($"{timestamp} ") { - Foreground = Brushes.DimGray // Use DimGray for a softer grey that works well on dark backgrounds + Foreground = Brushes.DimGray }); _logTextBlock.Inlines.Add(new Run($"[{level}] ") @@ -81,7 +73,7 @@ private void RefreshLogs() Foreground = Brushes.DarkRed }); } - _lastDisplayedLogCount = DebugHelper.LogEvents.Count(); + _lastDisplayedLogCount = bufferedEvents.Count; } } private IBrush GetBrushForLevel(LogEventLevel level) @@ -92,66 +84,66 @@ private IBrush GetBrushForLevel(LogEventLevel level) { StartPoint = new RelativePoint(0, 0, RelativeUnit.Relative), EndPoint = new RelativePoint(1, 1, RelativeUnit.Relative), - GradientStops = new GradientStops - { - new GradientStop(Color.FromRgb(60, 60, 60), 0), - new GradientStop(Color.FromRgb(40, 40, 40), 1) - } + GradientStops = + [ + new GradientStop(Color.FromRgb(60, 60, 60), 0), + new GradientStop(Color.FromRgb(40, 40, 40), 1) + ] }, LogEventLevel.Debug => new LinearGradientBrush { StartPoint = new RelativePoint(0, 0, RelativeUnit.Relative), EndPoint = new RelativePoint(1, 1, RelativeUnit.Relative), - GradientStops = new GradientStops - { - new GradientStop(Color.FromRgb(50, 100, 150), 0), - new GradientStop(Color.FromRgb(30, 70, 120), 1) - } + GradientStops = + [ + new GradientStop(Color.FromRgb(50, 100, 150), 0), + new GradientStop(Color.FromRgb(30, 70, 120), 1) + ] }, LogEventLevel.Information => new LinearGradientBrush { StartPoint = new RelativePoint(0, 0, RelativeUnit.Relative), EndPoint = new RelativePoint(1, 1, RelativeUnit.Relative), - GradientStops = new GradientStops - { - new GradientStop(Color.FromRgb(70, 130, 70), 0), - new GradientStop(Color.FromRgb(40, 90, 40), 1) - } + GradientStops = + [ + new GradientStop(Color.FromRgb(70, 130, 70), 0), + new GradientStop(Color.FromRgb(40, 90, 40), 1) + ] }, LogEventLevel.Warning => new LinearGradientBrush { StartPoint = new RelativePoint(0, 0, RelativeUnit.Relative), EndPoint = new RelativePoint(1, 1, RelativeUnit.Relative), - GradientStops = new GradientStops - { - new GradientStop(Color.FromRgb(200, 160, 0), 0), - new GradientStop(Color.FromRgb(150, 110, 0), 1) - } + GradientStops = + [ + new GradientStop(Color.FromRgb(200, 160, 0), 0), + new GradientStop(Color.FromRgb(150, 110, 0), 1) + ] }, LogEventLevel.Error => new LinearGradientBrush { StartPoint = new RelativePoint(0, 0, RelativeUnit.Relative), EndPoint = new RelativePoint(1, 1, RelativeUnit.Relative), - GradientStops = new GradientStops - { - new GradientStop(Color.FromRgb(180, 50, 50), 0), - new GradientStop(Color.FromRgb(130, 30, 30), 1) - } + GradientStops = + [ + new GradientStop(Color.FromRgb(180, 50, 50), 0), + new GradientStop(Color.FromRgb(130, 30, 30), 1) + ] }, LogEventLevel.Fatal => new LinearGradientBrush { StartPoint = new RelativePoint(0, 0, RelativeUnit.Relative), EndPoint = new RelativePoint(1, 1, RelativeUnit.Relative), - GradientStops = new GradientStops - { - new GradientStop(Color.FromRgb(100, 0, 0), 0), - new GradientStop(Color.FromRgb(30, 0, 0), 1) - } + GradientStops = + [ + new GradientStop(Color.FromRgb(100, 0, 0), 0), + new GradientStop(Color.FromRgb(30, 0, 0), 1) + ] }, _ => new SolidColorBrush(Colors.DimGray) @@ -170,13 +162,13 @@ private void OpenLogFolderButton_OnClick(object? Sender, RoutedEventArgs E) private void UploadLogButton_OnClick(object? Sender, RoutedEventArgs E) { - UploadManager.UploadText(_logTextBlock.Inlines?.OfType() + UploadManager.UploadText(_logTextBlock?.Inlines?.OfType() .Aggregate("", (current, run) => current + run.Text)!); } private void CopyButton_OnClick(object? Sender, RoutedEventArgs E) { - Clipboard?.SetTextAsync(_logTextBlock.Inlines?.OfType().Aggregate("", (current, run) => current + run.Text)!); + Clipboard?.SetTextAsync(_logTextBlock?.Inlines?.OfType().Aggregate("", (current, run) => current + run.Text)!); } private void LogTextBlock_OnSizeChanged(object? Sender, SizeChangedEventArgs e) diff --git a/SnapX.Core/DebugHelper.cs b/SnapX.Core/DebugHelper.cs index a49d37d7f..56cb17d12 100644 --- a/SnapX.Core/DebugHelper.cs +++ b/SnapX.Core/DebugHelper.cs @@ -2,8 +2,6 @@ using Serilog; -using Serilog.Events; -using Serilog.Sinks.InMemory; using Serilog.Sinks.SystemConsole.Themes; namespace SnapX.Core; @@ -12,8 +10,7 @@ public static class DebugHelper { public static ILogger? Logger { get; private set; } private static List messageBuffer = new(); - private static InMemorySink inMemorySink = new(); - public static IEnumerable LogEvents => inMemorySink.LogEvents; + public static ObservableSink observableSink { get; private set; } = new(); public static void Init(string logFilePath) { if (string.IsNullOrEmpty(logFilePath)) return; @@ -21,7 +18,7 @@ public static void Init(string logFilePath) #if DEBUG .MinimumLevel.Debug() #endif - .WriteTo.Sink(inMemorySink) + .WriteTo.Sink(observableSink) // If you run multiple SnapX instances, this will be the first to break. :) .WriteTo.Async(a => a.File(logFilePath, outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}]: {Message:lj}{NewLine}{Exception}", rollingInterval: RollingInterval.Day, buffered: true)); if (SnapX.LogToConsole) diff --git a/SnapX.Core/SnapX.Core.csproj b/SnapX.Core/SnapX.Core.csproj index 776f18cab..414d75c4d 100644 --- a/SnapX.Core/SnapX.Core.csproj +++ b/SnapX.Core/SnapX.Core.csproj @@ -71,7 +71,6 @@ - From 5107aababb143495260c1c6643412505dcac2c87 Mon Sep 17 00:00:00 2001 From: Brycen G Date: Fri, 11 Jul 2025 19:50:48 -0400 Subject: [PATCH 05/31] chore(Avalonia): acknowledge CommonUI namespaces --- SnapX.Avalonia/Views/About/AboutWindow.axaml | 8 ++++---- SnapX.Avalonia/Views/About/AboutWindow.axaml.cs | 4 ++-- SnapX.Avalonia/Views/Controls/ChangelogControl.axaml | 7 +++---- SnapX.Avalonia/Views/Controls/ChangelogControl.axaml.cs | 2 +- SnapX.Avalonia/Views/Settings/SettingsWindow.axaml.cs | 2 +- .../Views/Settings/Views/SettingsHomePageView.axaml.cs | 4 +--- .../Views/Settings/Views/SettingsMainView.axaml | 8 ++++---- 7 files changed, 16 insertions(+), 19 deletions(-) diff --git a/SnapX.Avalonia/Views/About/AboutWindow.axaml b/SnapX.Avalonia/Views/About/AboutWindow.axaml index 61fcbb904..8171d6581 100644 --- a/SnapX.Avalonia/Views/About/AboutWindow.axaml +++ b/SnapX.Avalonia/Views/About/AboutWindow.axaml @@ -8,18 +8,18 @@ d:DesignHeight="450" d:DesignWidth="800" mc:Ignorable="d" - x:Class="SnapX.Avalonia.AboutWindow" - x:DataType="viewModels:AboutWindowViewModel" + x:Class="SnapX.Avalonia.Views.About.AboutWindow" + x:DataType="viewModels1:AboutWindowViewModel" xmlns="https://github.com/avaloniaui" xmlns:avalonia="clr-namespace:FluentIcons.Avalonia;assembly=FluentIcons.Avalonia" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mdxaml="https://github.com/whistyun/Markdown.Avalonia.Tight" - xmlns:viewModels="clr-namespace:SnapX.Avalonia.ViewModels" + xmlns:viewModels1="clr-namespace:SnapX.CommonUI.ViewModels;assembly=SnapX.CommonUI" xmlns:windowing="clr-namespace:FluentAvalonia.UI.Windowing;assembly=FluentAvalonia" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> - + diff --git a/SnapX.Avalonia/Views/About/AboutWindow.axaml.cs b/SnapX.Avalonia/Views/About/AboutWindow.axaml.cs index 6b88537e2..565a1ab4f 100644 --- a/SnapX.Avalonia/Views/About/AboutWindow.axaml.cs +++ b/SnapX.Avalonia/Views/About/AboutWindow.axaml.cs @@ -8,11 +8,11 @@ using FluentAvalonia.Styling; using FluentAvalonia.UI.Media; using FluentAvalonia.UI.Windowing; -using SnapX.Avalonia.ViewModels; +using SnapX.CommonUI.ViewModels; using SnapX.Core; using SnapX.Core.Utils; -namespace SnapX.Avalonia; +namespace SnapX.Avalonia.Views.About; public partial class AboutWindow : AppWindow { diff --git a/SnapX.Avalonia/Views/Controls/ChangelogControl.axaml b/SnapX.Avalonia/Views/Controls/ChangelogControl.axaml index b4cd64994..7902f1f07 100644 --- a/SnapX.Avalonia/Views/Controls/ChangelogControl.axaml +++ b/SnapX.Avalonia/Views/Controls/ChangelogControl.axaml @@ -4,17 +4,16 @@ d:DesignWidth="800" mc:Ignorable="d" x:Class="SnapX.Avalonia.Views.Controls.ChangelogControl" - x:DataType="viewModels:ChangelogViewModel" + x:DataType="viewModels1:ChangelogViewModel" xmlns="https://github.com/avaloniaui" xmlns:commonUi="clr-namespace:SnapX.CommonUI;assembly=SnapX.CommonUI" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:fa="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" xmlns:markdown="clr-namespace:Markdown.Avalonia;assembly=Markdown.Avalonia" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:viewModels="clr-namespace:SnapX.Avalonia.ViewModels" + xmlns:viewModels1="clr-namespace:SnapX.CommonUI.ViewModels;assembly=SnapX.CommonUI" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> - + diff --git a/SnapX.Avalonia/Views/Controls/ChangelogControl.axaml.cs b/SnapX.Avalonia/Views/Controls/ChangelogControl.axaml.cs index 14c482f8d..0b77b4bea 100644 --- a/SnapX.Avalonia/Views/Controls/ChangelogControl.axaml.cs +++ b/SnapX.Avalonia/Views/Controls/ChangelogControl.axaml.cs @@ -1,6 +1,6 @@ using Avalonia.Controls; using Avalonia.Interactivity; -using SnapX.Avalonia.ViewModels; +using SnapX.CommonUI.ViewModels; namespace SnapX.Avalonia.Views.Controls; diff --git a/SnapX.Avalonia/Views/Settings/SettingsWindow.axaml.cs b/SnapX.Avalonia/Views/Settings/SettingsWindow.axaml.cs index cf275b9c8..984136645 100644 --- a/SnapX.Avalonia/Views/Settings/SettingsWindow.axaml.cs +++ b/SnapX.Avalonia/Views/Settings/SettingsWindow.axaml.cs @@ -1,5 +1,5 @@ using FluentAvalonia.UI.Windowing; -using SnapX.Avalonia.ViewModels; +using SnapX.CommonUI.ViewModels; namespace SnapX.Avalonia.Views.Settings; diff --git a/SnapX.Avalonia/Views/Settings/Views/SettingsHomePageView.axaml.cs b/SnapX.Avalonia/Views/Settings/Views/SettingsHomePageView.axaml.cs index dec3c44b0..5a231e25d 100644 --- a/SnapX.Avalonia/Views/Settings/Views/SettingsHomePageView.axaml.cs +++ b/SnapX.Avalonia/Views/Settings/Views/SettingsHomePageView.axaml.cs @@ -1,18 +1,16 @@ using Avalonia.Controls; using Avalonia.Media; -using SnapX.Avalonia.ViewModels; +using SnapX.CommonUI.ViewModels; using SnapX.Core; namespace SnapX.Avalonia.Views.Settings.Views; public partial class SettingsHomePageView : UserControl { - private SettingsHomePageViewVM ViewModel; public SettingsHomePageView(SettingsHomePageViewVM vm) { DataContext = vm; - ViewModel = vm; InitializeComponent(); var itemsAsList = FontManager.Current.SystemFonts .OrderBy(font => font.Name) diff --git a/SnapX.Avalonia/Views/Settings/Views/SettingsMainView.axaml b/SnapX.Avalonia/Views/Settings/Views/SettingsMainView.axaml index 4958c2476..4292005c5 100644 --- a/SnapX.Avalonia/Views/Settings/Views/SettingsMainView.axaml +++ b/SnapX.Avalonia/Views/Settings/Views/SettingsMainView.axaml @@ -3,18 +3,18 @@ d:DesignWidth="800" mc:Ignorable="d" x:Class="SnapX.Avalonia.Views.Settings.Views.SettingsMainView" - x:DataType="viewModels1:SettingsMainViewVM" + x:DataType="viewModels:SettingsMainViewVM" xmlns="https://github.com/avaloniaui" xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" xmlns:core="clr-namespace:SnapX.Core;assembly=SnapX.Core" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:fluent="clr-namespace:FluentIcons.Avalonia.Fluent;assembly=FluentIcons.Avalonia.Fluent" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:viewModels1="clr-namespace:SnapX.Avalonia.ViewModels" xmlns:views="clr-namespace:SnapX.Avalonia.Views.Settings.Views" - xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:viewModels="clr-namespace:SnapX.CommonUI.ViewModels;assembly=SnapX.CommonUI"> - + Date: Fri, 11 Jul 2025 19:52:22 -0400 Subject: [PATCH 06/31] test(build): initial tests --- tests/Build.Tests/Build.Tests.csproj | 22 ++++++++++ tests/Build.Tests/BuildTests.cs | 65 ++++++++++++++++++++++++++++ tests/Build.Tests/GlobalHooks.cs | 23 ++++++++++ 3 files changed, 110 insertions(+) create mode 100644 tests/Build.Tests/Build.Tests.csproj create mode 100644 tests/Build.Tests/BuildTests.cs create mode 100644 tests/Build.Tests/GlobalHooks.cs diff --git a/tests/Build.Tests/Build.Tests.csproj b/tests/Build.Tests/Build.Tests.csproj new file mode 100644 index 000000000..6c4f38f52 --- /dev/null +++ b/tests/Build.Tests/Build.Tests.csproj @@ -0,0 +1,22 @@ + + + + enable + enable + Exe + true + true + + + + + + + + + + + + + + diff --git a/tests/Build.Tests/BuildTests.cs b/tests/Build.Tests/BuildTests.cs new file mode 100644 index 000000000..d8a30e2ce --- /dev/null +++ b/tests/Build.Tests/BuildTests.cs @@ -0,0 +1,65 @@ +namespace DefaultNamespace; + +public class BuildTests +{ + private static readonly IBuildLogger logger = new ConsoleLogger(); + private static readonly ICommandRunner commandRunner = new CommandRunner(logger); + private static readonly FS fileSystem = new(logger, commandRunner); + + [Test] + public async Task Builds() + { + var cli = new CLI(); + BuildConfig? config = null; + await cli.InvokeAsync([], buildconfig => + { + config = buildconfig; + return Task.CompletedTask; + }); + if (config is null) throw new NullReferenceException(nameof(config)); + var buildProcessor = new Build(logger, commandRunner, fileSystem, config); + + await buildProcessor.ProcessBuildProject(config.ProjectsToBuild[0]); + } + + [Test, DependsOn(nameof(Builds))] + public async Task Installs() + { + // var snapx = new SnapX.Core.SnapX(); + // #if RELEASE + // snapx.silenceLogging(); + // #elif DEBUG + // #else + // snapx.silenceLogging(); + // #endif + // snapx.start([]); + // + // var CLIManager = snapx.GetCLIManager(); + // + // Task.Run(() => CLIManager.UseCommandLineArgs().GetAwaiter().GetResult()).ConfigureAwait(false).GetAwaiter().GetResult(); + var cli = new CLI(); + BuildConfig? config = null; + await cli.InvokeAsync([], buildconfig => + { + config = buildconfig; + return Task.CompletedTask; + }); + if (config is null) throw new NullReferenceException(nameof(config)); + config.Prefix = Path.Join(Path.DirectorySeparatorChar.ToString(), "usr"); + config.DestDir = Path.Join(AppContext.BaseDirectory, nameof(BuildTests)); + + var installer = new Install(logger, commandRunner, fileSystem, config); + + await installer.ProcessInstall(); + } + [After(Test)] + public void Cleanup() + { + var testDir = Path.Join(AppContext.BaseDirectory, nameof(BuildTests)); + if (Directory.Exists(testDir)) + { + Directory.Delete(testDir, recursive: true); + } + } + +} diff --git a/tests/Build.Tests/GlobalHooks.cs b/tests/Build.Tests/GlobalHooks.cs new file mode 100644 index 000000000..6275eee25 --- /dev/null +++ b/tests/Build.Tests/GlobalHooks.cs @@ -0,0 +1,23 @@ +// You can use attributes at the assembly level to apply to all tests in the assembly +// Here you could define global logic that would affect all tests + +[assembly: Retry(3)] +[assembly: System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + +namespace DefaultNamespace; + + +public class GlobalHooks +{ + [Before(TestSession)] + public static void SetUp() + { + Console.WriteLine(@"Or you can define methods that do stuff before..."); + } + + [After(TestSession)] + public static void CleanUp() + { + Console.WriteLine(@"...and after!"); + } +} From 29136bb5882232c1a3838f415ed276c1075966db Mon Sep 17 00:00:00 2001 From: Brycen G Date: Fri, 11 Jul 2025 19:53:19 -0400 Subject: [PATCH 07/31] feat(Avalonia): allow Avalonia to be controlled by settings --- SnapX.Avalonia/App.axaml.cs | 52 ++-------- SnapX.Avalonia/OSTray.cs | 190 +++++++++++++++++++---------------- SnapX.Avalonia/Program.cs | 6 +- SnapX.Core/SettingManager.cs | 26 +++-- SnapX.Core/SnapX.cs | 50 ++++++--- 5 files changed, 163 insertions(+), 161 deletions(-) diff --git a/SnapX.Avalonia/App.axaml.cs b/SnapX.Avalonia/App.axaml.cs index 76d35e934..e21e602ae 100644 --- a/SnapX.Avalonia/App.axaml.cs +++ b/SnapX.Avalonia/App.axaml.cs @@ -7,16 +7,13 @@ using Avalonia.Media; using Avalonia.Styling; using CommunityToolkit.Mvvm.DependencyInjection; -using CommunityToolkit.Mvvm.Messaging; using FluentAvalonia.UI.Windowing; -using Microsoft.Extensions.DependencyInjection; -using Serilog; using SnapX.Avalonia.ViewModels; using SnapX.Avalonia.Views; +using SnapX.Avalonia.Views.About; using SnapX.Avalonia.Views.Settings; -using SnapX.Avalonia.Views.Settings.Views; -using SnapX.CommonUI.ViewModels; using SnapX.Core; +using SnapX.Core.Interfaces; using SnapX.Core.Utils; using SnapX.Core.Utils.Native; @@ -31,23 +28,13 @@ public App() public static SnapXAvalonia SnapX { get; private set; } = null!; public static MainWindow? MyMainWindow { get; private set; } - public static string TrayTitle => $"SnapX v{SimpleVersion()}"; - - private static string SimpleVersion() - { - var version = Version.Parse(Helpers.GetApplicationVersion()); - var versionString = $"{version.Major}.{version.Minor}.{version.Revision}"; - if (version.Build > 0) - versionString += $".{version.Build}"; - return versionString; - } public override void Initialize() { SnapX = new SnapXAvalonia(); // SnapX.setQualifier(" UI"); AvaloniaXamlLoader.Load(this); - AppDomain.CurrentDomain.UnhandledException += (Sender, Args) => + AppDomain.CurrentDomain.UnhandledException += (_, Args) => { ShowErrorDialog(Lang.UnhandledException, Args.ExceptionObject as Exception); }; @@ -229,13 +216,7 @@ public override void OnFrameworkInitializationCompleted() { var locator = new ViewLocator(); DataTemplates.Add(locator); - var services = new ServiceCollection(); - ConfigureServices(services); - var provider = services.BuildServiceProvider(); - - Ioc.Default.ConfigureServices(provider); - Ioc.Default.AddStaticLogging(); var vm = Ioc.Default.GetRequiredService(); switch (ApplicationLifetime) @@ -294,6 +275,8 @@ public override void OnFrameworkInitializationCompleted() MyMainWindow = Window; desktop.MainWindow = Window; + var tray = new OSTray(this, Ioc.Default.GetRequiredService()); + tray.display(); break; } case ISingleViewApplicationLifetime singleView when SnapX.isSilent(): @@ -344,7 +327,7 @@ public static void CreateAboutWindowStatic() aboutWindow.Show(); } } - public static void NativeMenuAboutSnapXClick(object? Sender, EventArgs E) + public void NativeMenuAboutSnapXClick(object? Sender, EventArgs E) { CreateAboutWindowStatic(); } @@ -366,27 +349,4 @@ public static void CreateSettingsWindowStatic() settingsWindow.Show(); } } - - public static void ConfigureServices(IServiceCollection services) - { - services.AddLogging(loggingBuilder => - loggingBuilder.AddSerilog(dispose: true)); - - - services.AddTransient(); - services.AddSingleton(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - - services.AddTransient(); - services.AddSingleton(); - - services.AddTransient(); - services.AddSingleton(); - - services.AddSingleton(WeakReferenceMessenger.Default); - } } diff --git a/SnapX.Avalonia/OSTray.cs b/SnapX.Avalonia/OSTray.cs index aa8f09113..0a3e2f36a 100644 --- a/SnapX.Avalonia/OSTray.cs +++ b/SnapX.Avalonia/OSTray.cs @@ -3,109 +3,121 @@ using Avalonia.Platform; using CommunityToolkit.Mvvm.DependencyInjection; using CommunityToolkit.Mvvm.Input; -using Serilog; using SnapX.Avalonia.ViewModels; using SnapX.Avalonia.Views; -using SnapX.Core.SharpCapture; +using SnapX.Core.Interfaces; using SnapX.Core.Job; +using SnapX.Core.SharpCapture; using SnapX.Core.Utils; namespace SnapX.Avalonia; -public partial class OSTray(App Current, ILogger Logger) +public partial class OSTray(App Current, ILoggerService Logger) { + private static string TrayTitle => $"{Core.SnapX.AppName} v{SimpleVersion()}"; + + private static string SimpleVersion() + { + var version = Version.Parse(Helpers.GetApplicationVersion()); + var versionString = $"{version.Major}.{version.Minor}.{version.Revision}"; + if (version.Build > 0) + versionString += $".{version.Build}"; + return versionString; + } public void display() { - var logoBitmap = new Bitmap(AssetLoader.Open(new Uri("avares://snapx-ui/SnapX_Logo.png"))); - var trayIcon = new TrayIcon - { - Icon = new WindowIcon(logoBitmap), - ToolTipText = Core.SnapX.AppName, - Command = OpenSnapXCommand - }; - - var menu = new NativeMenu(); - menu.Opening += NativeMenu_OnOpening; - menu.NeedsUpdate += NativeMenu_OnNeedsUpdate; - - var about = new NativeMenuItem(TrayTitle) - { - Icon = logoBitmap, - ToolTip = Lang.AboutSnapX - }; - about.Click += NativeMenuItem_SnapX_OnClick; - menu.Items.Add(about); - menu.Items.Add(new NativeMenuItemSeparator()); - - var capture = new NativeMenuItem("Capture") { Menu = new NativeMenu() }; - var full = new NativeMenuItem(Lang.UI_Capture_Fullscreen); - full.Click += NativeMenuItem_Capture_Fullscreen_OnClick; - capture.Menu.Items.Add(full); - - var windowPicker = new NativeMenuItem(Lang.UI_Dropdown_Window) - { - Menu = new NativeMenu - { - new NativeMenuItem("SnapX UI") { Icon = logoBitmap }, - new NativeMenuItem("Marvel Rivals") { Icon = logoBitmap }, - new NativeMenuItem("Man of Steel (2013)") { Icon = logoBitmap } - } - }; - capture.Menu.Items.Add(windowPicker); - - var monitorPicker = new NativeMenuItem(Lang.UI_Dropdown_Monitor) { Menu = [] }; - monitorPicker.Menu.NeedsUpdate += NativeMenu_OnNeedsUpdate; - capture.Menu.Items.Add(monitorPicker); - - capture.Menu.Items.Add(new NativeMenuItem("Region")); - capture.Menu.Items.Add(new NativeMenuItem("Region (Light)")); - capture.Menu.Items.Add(new NativeMenuItem("Region (Transparent)")); - menu.Items.Add(capture); - - menu.Items.Add(new NativeMenuItem("Upload") - { - Menu = new NativeMenu - { - new NativeMenuItem("Upload File..."), - new NativeMenuItem("Upload Folder..."), - new NativeMenuItem("Upload from clipboard..."), - new NativeMenuItem("Upload text..."), - new NativeMenuItem("Drag and drop upload..."), - new NativeMenuItem("Shorten URL..."), - new NativeMenuItem("Tweet message...") - } - }); - var captureFullscreenMenuItem = new NativeMenuItem("Capture entire screen"); - captureFullscreenMenuItem.Click += NativeMenuItem_Capture_Fullscreen_OnClick; - var captureActiveWindowMenuItem = new NativeMenuItem("Capture active window"); - captureActiveWindowMenuItem.Click += NativeMenuItem_Workflows_CaptureActiveWindow_OnClick; - var captureActiveScreenMenuItem = new NativeMenuItem("Capture active screen"); - captureActiveScreenMenuItem.Click += NativeMenuItem_Workflows_CaptureActiveScreen_OnClick; - var workflows = new NativeMenuItem("Workflows") - { - Menu = - [ - captureFullscreenMenuItem, + var logoBitmap = new Bitmap(AssetLoader.Open(new Uri("avares://snapx-ui/SnapX_Logo.png"))); + var trayIcon = new TrayIcon + { + Icon = new WindowIcon(logoBitmap), + ToolTipText = Core.SnapX.AppName, + Command = OpenSnapXCommand + }; + + var menu = new NativeMenu(); + menu.Opening += NativeMenu_OnOpening; + menu.NeedsUpdate += NativeMenu_OnNeedsUpdate; + + var about = new NativeMenuItem(TrayTitle) + { + Icon = logoBitmap, + ToolTip = Lang.AboutSnapX + }; + about.Click += NativeMenuItem_SnapX_OnClick; + menu.Items.Add(about); + menu.Items.Add(new NativeMenuItemSeparator()); + + var capture = new NativeMenuItem("Capture") { Menu = new NativeMenu() }; + var full = new NativeMenuItem(Lang.UI_Capture_Fullscreen); + full.Click += NativeMenuItem_Capture_Fullscreen_OnClick; + capture.Menu.Items.Add(full); + + var windowPicker = new NativeMenuItem(Lang.UI_Dropdown_Window) + { + Menu = + [ + new NativeMenuItem("SnapX UI") { Icon = logoBitmap }, + new NativeMenuItem("Marvel Rivals") { Icon = logoBitmap }, + new NativeMenuItem("Man of Steel (2013)") { Icon = logoBitmap } + ] + }; + capture.Menu.Items.Add(windowPicker); + + var monitorPicker = new NativeMenuItem(Lang.UI_Dropdown_Monitor) { Menu = [] }; + monitorPicker.Menu.NeedsUpdate += NativeMenu_OnNeedsUpdate; + capture.Menu.Items.Add(monitorPicker); + + capture.Menu.Items.Add(new NativeMenuItem("Region")); + capture.Menu.Items.Add(new NativeMenuItem("Region (Light)")); + capture.Menu.Items.Add(new NativeMenuItem("Region (Transparent)")); + menu.Items.Add(capture); + + menu.Items.Add(new NativeMenuItem("Upload") + { + Menu = + [ + new NativeMenuItem("Upload File..."), + new NativeMenuItem("Upload Folder..."), + new NativeMenuItem("Upload from clipboard..."), + new NativeMenuItem("Upload text..."), + new NativeMenuItem("Drag and drop upload..."), + new NativeMenuItem("Shorten URL..."), + new NativeMenuItem("Tweet message...") + ] + }); + var captureFullscreenMenuItem = new NativeMenuItem("Capture entire screen"); + captureFullscreenMenuItem.Click += NativeMenuItem_Capture_Fullscreen_OnClick; + var captureActiveWindowMenuItem = new NativeMenuItem("Capture active window"); + captureActiveWindowMenuItem.Click += NativeMenuItem_Workflows_CaptureActiveWindow_OnClick; + var captureActiveScreenMenuItem = new NativeMenuItem("Capture active screen"); + captureActiveScreenMenuItem.Click += NativeMenuItem_Workflows_CaptureActiveScreen_OnClick; + var workflows = new NativeMenuItem("Workflows") + { + Menu = + [ + captureFullscreenMenuItem, captureActiveScreenMenuItem, captureActiveWindowMenuItem, ] - }; + }; - menu.Items.Add(workflows); + menu.Items.Add(workflows); - menu.Items.Add(new NativeMenuItemSeparator()); + menu.Items.Add(new NativeMenuItemSeparator()); - var open = new NativeMenuItem("Open"); - open.Command = OpenSnapXCommand; - menu.Items.Add(open); + var open = new NativeMenuItem("Open") + { + Command = OpenSnapXCommand + }; + menu.Items.Add(open); - var quit = new NativeMenuItem("Quit"); - quit.Click += NativeMenuItem_Quit_OnClick; - menu.Items.Add(quit); + var quit = new NativeMenuItem("Quit"); + quit.Click += NativeMenuItem_Quit_OnClick; + menu.Items.Add(quit); - trayIcon.Menu = menu; + trayIcon.Menu = menu; - TrayIcon.SetIcons(Current, [trayIcon]); + TrayIcon.SetIcons(Current, [trayIcon]); } private void NativeMenuItem_Quit_OnClick(object? Sender, EventArgs E) { @@ -113,7 +125,7 @@ private void NativeMenuItem_Quit_OnClick(object? Sender, EventArgs E) } private void NativeMenuItem_SnapX_OnClick(object? Sender, EventArgs E) { - App.NativeMenuAboutSnapXClick(Sender, E); + Current.NativeMenuAboutSnapXClick(Sender, E); } private void NativeMenuItem_Capture_Fullscreen_OnClick(object? Sender, EventArgs E) @@ -123,15 +135,17 @@ private void NativeMenuItem_Capture_Fullscreen_OnClick(object? Sender, EventArgs private void NativeMenuItem_Workflows_CaptureActiveScreen_OnClick(object? Sender, EventArgs E) { - new CaptureActiveMonitor().CaptureAsync(TaskSettings.GetDefaultTaskSettings()); + var capture = Ioc.Default.GetRequiredService(); + capture.CaptureAsync(TaskSettings.GetDefaultTaskSettings()); } private void NativeMenuItem_Workflows_CaptureActiveWindow_OnClick(object? Sender, EventArgs E) { - new CaptureActiveWindow().Capture(TaskSettings.GetDefaultTaskSettings()); + var capture = Ioc.Default.GetRequiredService(); + capture.CaptureAsync(TaskSettings.GetDefaultTaskSettings()); } - private void NativeMenuItem_Open_OnClick(object? Sender, EventArgs E) + private void NativeMenuItem_Open_OnClick(object? _, EventArgs _2) { var MyMainWindow = App.MyMainWindow; if (!MyMainWindow?.IsLoaded ?? false) diff --git a/SnapX.Avalonia/Program.cs b/SnapX.Avalonia/Program.cs index 47789765e..de20b7bb4 100644 --- a/SnapX.Avalonia/Program.cs +++ b/SnapX.Avalonia/Program.cs @@ -5,6 +5,10 @@ using Avalonia.Media; using SnapX.Avalonia; +var snapx = new SnapXAvalonia(); + +snapx.loadApplicationSettingsPartial(); + BuildAvaloniaApp() .StartWithClassicDesktopLifetime(args); @@ -23,7 +27,7 @@ static AppBuilder BuildAvaloniaApp() { new() { - FontFamily = "Inter" + FontFamily = "fonts:Inter#Inter" }, new() { diff --git a/SnapX.Core/SettingManager.cs b/SnapX.Core/SettingManager.cs index 2cccf0048..252bbc056 100644 --- a/SnapX.Core/SettingManager.cs +++ b/SnapX.Core/SettingManager.cs @@ -12,6 +12,7 @@ using Esatto.Win32.Registry; #endif using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; using SnapX.Core.History; using SnapX.Core.Hotkey; using SnapX.Core.Job; @@ -22,13 +23,13 @@ namespace SnapX.Core; -[JsonSerializable(typeof(RootConfiguration))] +[JsonSerializable(typeof(ApplicationConfig))] [JsonSerializable(typeof(IConfiguration))] [JsonSerializable(typeof(UploadersConfig))] [JsonSerializable(typeof(HotkeysConfig))] internal partial class SettingsContext : JsonSerializerContext; -internal static class SettingManager +internal class SettingManager(IServiceProvider serviceProvider) { private const string ApplicationConfigFileName = "ApplicationConfig.json"; @@ -90,21 +91,20 @@ private static string HotkeysConfigFilePath public static string? SnapshotFolder => Path.Combine(SnapX.PersonalFolder, "Snapshots"); - private static RootConfiguration Settings { get => SnapX.Settings; set => SnapX.Settings = value; } - private static TaskSettings DefaultTaskSettings { get => SnapX.DefaultTaskSettings; set => SnapX.DefaultTaskSettings = value; } + private static ApplicationConfig Settings { get => SnapX.Settings; set => SnapX.Settings = value; } + private static TaskSettings? DefaultTaskSettings { get => SnapX.DefaultTaskSettings; set => SnapX.DefaultTaskSettings = value; } private static UploadersConfig UploadersConfig { get => SnapX.UploadersConfig; set => SnapX.UploadersConfig = value; } private static HotkeysConfig HotkeysConfig { get => SnapX.HotkeysConfig; set => SnapX.HotkeysConfig = value; } - private static VersionEnforcer theLaw; + private static VersionEnforcer? theLaw; private static ManualResetEvent uploadersConfigResetEvent = new(false); private static ManualResetEvent hotkeysConfigResetEvent = new(false); [UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "")] - public static void LoadSettings() + public void LoadSettings() { - theLaw = new VersionEnforcer(SnapX.LockDirectory); + theLaw = serviceProvider.GetRequiredService(); theLaw.Enforce(); - LoadApplicationConfig(); LoadUploadersConfig(); LoadHotkeysConfig(); } @@ -150,7 +150,7 @@ public static void LoadApplicationConfig(bool fallbackSupport = true) { // DebugHelper.WriteLine($"{kv.Key} = {kv.Value}"); } - var settings = new RootConfiguration(); + var settings = new ApplicationConfig(); SnapX.Configuration.Bind(settings); Settings = settings; if (string.IsNullOrWhiteSpace(Settings.SQLitePath)) @@ -279,6 +279,12 @@ private static void ApplicationConfigBackwardCompatibilityTasks() .OrderBy(name => name) // Ensure migrations are processed in numerical order .ToList(); + if (SnapX.DbConnection is null) + { + DebugHelper.WriteLine("SnapX.DbConnection is null, skipping backward compatibility tasks."); + return; + } + // Ensure MigrationLog table exists for the checks below // This is crucial if it's the very first time running migrations. SnapX.DbConnection.Execute(@" @@ -472,7 +478,7 @@ private static void HotkeysConfigBackwardCompatibilityTasks() { } - public static void Dispose() => theLaw.Dispose(); + public static void Dispose() => theLaw?.Dispose(); public static void CleanupHotkeysConfig() { foreach (var taskSettings in HotkeysConfig.Hotkeys.Select(x => x.TaskSettings)) diff --git a/SnapX.Core/SnapX.cs b/SnapX.Core/SnapX.cs index 06d45e997..2f0ab672e 100644 --- a/SnapX.Core/SnapX.cs +++ b/SnapX.Core/SnapX.cs @@ -1,16 +1,18 @@ using System.Diagnostics; -using System.Reflection; using System.Text; using System.Text.Json; using Aptabase.Core; using Dapper; using Microsoft.Data.Sqlite; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Serilog; using SnapX.Core.CLI; using SnapX.Core.Hotkey; +using SnapX.Core.Interfaces; using SnapX.Core.Job; +using SnapX.Core.Services; using SnapX.Core.Upload; using SnapX.Core.Utils; using SnapX.Core.Utils.Extensions; @@ -23,7 +25,7 @@ namespace SnapX.Core; -public class SnapX +public class SnapX(IServiceProvider serviceProvider) { public const string AppName = "SnapX"; public static string Qualifier { get; set; } = ""; @@ -88,6 +90,18 @@ public static void quit() { CloseSequence(); } + + public static void ConfigureServices(ServiceCollection services) + { + services.AddLogging(loggingBuilder => + loggingBuilder.AddSerilog(dispose: true)); + services.AddSingleton(_ => new SerilogLogService(LogsFilePath, true, Configuration)); + services.AddSingleton(provider => + { + var logger = provider.GetRequiredService(); + return new VersionEnforcer(LockDirectory, logger); + }); + } public static string Title { get @@ -119,13 +133,13 @@ public static string Title public static bool IgnoreHotkeyWarning { get; private set; } public static bool PuushMode { get; private set; } - public static RootConfiguration Settings { get; set; } = new(); + public static ApplicationConfig Settings { get; set; } = new(); public static List Flags { get; set; } = new(); internal static IConfiguration Configuration { get; set; } - internal static TaskSettings DefaultTaskSettings { get; set; } = TaskSettings.GetDefaultTaskSettings(); - internal static UploadersConfig UploadersConfig { get; set; } - internal static HotkeysConfig HotkeysConfig { get; set; } + internal static TaskSettings? DefaultTaskSettings { get; set; } = TaskSettings.GetDefaultTaskSettings(); + internal static UploadersConfig? UploadersConfig { get; set; } = new(); + internal static HotkeysConfig? HotkeysConfig { get; set; } = new(); internal static Stopwatch StartTimer { get; private set; } internal static HotkeyManager HotkeyManager { get; set; } @@ -162,11 +176,10 @@ private static string PersonalPathConfigFilePath AppName, PersonalPathConfigFileName); private static readonly string PortableCheckFilePath = FileHelpers.GetAbsolutePath("Portable"); - public static EventAggregator EventAggregator { get; } = new(); private static string CustomPersonalPath { get; set; } private static string CustomConfigPath { get; set; } - public static SqliteConnection DbConnection { get; set; } + public static SqliteConnection? DbConnection { get; set; } public static string ShortenPath(string? path) => OperatingSystem.IsWindows() ? path : path.Replace(Environment.GetEnvironmentVariable("HOME") ?? "", "~"); @@ -263,11 +276,10 @@ public void shutdown() { CloseSequence(); } - public Assembly[] GetAssemblies() => AppDomain.CurrentDomain.GetAssemblies(); public void start(string?[] args) { HandleExceptions(); - + new SettingManager(serviceProvider).LoadSettings(); StartTimer = Stopwatch.StartNew(); // TODO: Implement CLI in a better way than what it is now. CLIManager = new SnapXCLIManager(args); @@ -290,7 +302,11 @@ public void start(string?[] args) } public long getStartupTime() => StartTimer.ElapsedMilliseconds; - public EventAggregator getEventAggregator() => EventAggregator; + public static IServiceCollection ConfigureCoreSnapXServices(IServiceCollection services, IConfiguration configuration) + { + services.AddSingleton(configuration); + return services; + } public bool isSilent() => SilentRun; public static object? aptabaseClientObject; @@ -302,8 +318,12 @@ public static bool CanUpload() => public static bool CanAutoUpdate() => !FeatureFlags.DisableAutoUpdates && Settings.AutoCheckUpdate; + public void loadApplicationSettingsPartial() + { + SettingManager.LoadApplicationConfig(); + } [DapperAot] - private static void Run() + private void Run() { DebugHelper.WriteLine("SnapX starting."); DebugHelper.WriteLine("Version: " + VersionText); @@ -404,7 +424,6 @@ private static void Run() { DebugHelper.WriteLine($"DB: {Args.CurrentState}"); }; - SettingManager.LoadSettings(); if (TelemetryEnabled()) { var loggerFactory = LoggerFactory.Create(builder => @@ -423,7 +442,7 @@ private static void Run() IsDebugMode = false #endif }, logger); - var telemetry = new Telemetry(DbConnection, aptabaseClient); + var telemetry = new Telemetry(DbConnection, aptabaseClient, serviceProvider.GetRequiredService()); aptabaseClientObject = aptabaseClient; telemetry.TrackEvent("app_started", new Dictionary { @@ -452,7 +471,6 @@ private static void Run() #if DEBUG options.Environment = "development"; options.CreateHttpMessageHandler = () => new LoggingHttpMessageHandler(new SentryHttpMessageHandler(), DebugHelper.Logger); - options.DisableSentryHttpMessageHandler = true; #else options.Environment = "production"; #endif @@ -512,7 +530,7 @@ static void RunWithTimeout(Func taskFactory, string description = "SQLite task.GetAwaiter().GetResult(); // propagate exceptions } public SnapXCLIManager GetCLIManager() => CLIManager; - public RootConfiguration GetConfiguration() => Settings; + public ApplicationConfig GetConfiguration() => Settings; public static void CloseSequence() { From 8581290a7553b02c7f2a6afc8b3e47bd34ab5784 Mon Sep 17 00:00:00 2001 From: Brycen G Date: Fri, 11 Jul 2025 19:55:30 -0400 Subject: [PATCH 08/31] fix(Core): use proper types for ApplicationConfig Color still needs a string converter. --- SnapX.Core/ApplicationConfig.cs | 188 +------------- SnapX.Core/Hotkey/HotkeyInfo.cs | 23 +- SnapX.Core/Hotkey/HotkeySettings.cs | 13 +- SnapX.Core/Hotkey/HotkeysConfig.cs | 2 +- SnapX.Core/Media/GradientInfo.cs | 136 ++++++++++ .../RegionCaptureOptions.cs | 23 +- .../ScreenRecording/ScreenRecordingOptions.cs | 2 +- SnapX.Core/SnapXResources.cs | 239 ++++++++++++++++++ SnapX.Core/Utils/Extensions/Extensions.cs | 6 +- 9 files changed, 420 insertions(+), 212 deletions(-) create mode 100644 SnapX.Core/Media/GradientInfo.cs rename SnapX.Core/{ScreenCapture => SharpCapture}/RegionCaptureOptions.cs (87%) diff --git a/SnapX.Core/ApplicationConfig.cs b/SnapX.Core/ApplicationConfig.cs index f61473933..741e93c4a 100644 --- a/SnapX.Core/ApplicationConfig.cs +++ b/SnapX.Core/ApplicationConfig.cs @@ -1,179 +1,21 @@ using System.ComponentModel; using SixLabors.ImageSharp; using SnapX.Core.History; +using SnapX.Core.ImageEffects; using SnapX.Core.Job; using SnapX.Core.Utils; using SnapX.Core.Utils.Miscellaneous; namespace SnapX.Core; -public class GradientColor +public class ApplicationConfig { - public string Color { get; set; } - public double Location { get; set; } -} - -public class PinToScreenOptions -{ - public int InitialScale { get; set; } - public int ScaleStep { get; set; } - public bool HighQualityScale { get; set; } - public int InitialOpacity { get; set; } - public int OpacityStep { get; set; } - public string Placement { get; set; } - public int PlacementOffset { get; set; } - public bool TopMost { get; set; } - public bool KeepCenterLocation { get; set; } - public string BackgroundColor { get; set; } - public bool Shadow { get; set; } - public bool Border { get; set; } - public int BorderSize { get; set; } - public string BorderColor { get; set; } - public string MinimizeSize { get; set; } -} - -public class ImageBeautifierOptions -{ - public int Margin { get; set; } - public int Padding { get; set; } - public bool SmartPadding { get; set; } - public int RoundedCorner { get; set; } - public int ShadowRadius { get; set; } - public int ShadowOpacity { get; set; } - public int ShadowDistance { get; set; } - public int ShadowAngle { get; set; } - public string ShadowColor { get; set; } - public string BackgroundType { get; set; } - public BackgroundGradient BackgroundGradient { get; set; } - public string BackgroundColor { get; set; } - public string BackgroundImageFilePath { get; set; } -} - -public class BackgroundGradient -{ - public string Type { get; set; } - public List Colors { get; set; } -} - -public class ImageCombinerOptions -{ - public string Orientation { get; set; } - public string Alignment { get; set; } - public int Space { get; set; } - public int WrapAfter { get; set; } - public bool AutoFillBackground { get; set; } -} - -public class VideoConverterOptions -{ - public string InputFilePath { get; set; } - public string OutputFolderPath { get; set; } - public string OutputFileName { get; set; } - public string VideoCodec { get; set; } - public int VideoQuality { get; set; } - public bool VideoQualityUseBitrate { get; set; } - public int VideoQualityBitrate { get; set; } - public bool UseCustomArguments { get; set; } - public string CustomArguments { get; set; } - public bool AutoOpenFolder { get; set; } -} - -public class VideoThumbnailOptions -{ - public string DefaultOutputDirectory { get; set; } - public string LastVideoPath { get; set; } - public string OutputLocation { get; set; } - public string CustomOutputDirectory { get; set; } - public string ImageFormat { get; set; } - public int ThumbnailCount { get; set; } - public string FilenameSuffix { get; set; } - public bool RandomFrame { get; set; } - public bool UploadThumbnails { get; set; } - public bool KeepScreenshots { get; set; } - public bool OpenDirectory { get; set; } - public int MaxThumbnailWidth { get; set; } - public bool CombineScreenshots { get; set; } - public int Padding { get; set; } - public int Spacing { get; set; } - public int ColumnCount { get; set; } - public bool AddVideoInfo { get; set; } - public bool AddTimestamp { get; set; } - public bool DrawShadow { get; set; } - public bool DrawBorder { get; set; } -} - -public class BorderlessWindowSettings -{ - public bool RememberWindowTitle { get; set; } - public string WindowTitle { get; set; } - public bool AutoCloseWindow { get; set; } - public bool ExcludeTaskbarArea { get; set; } -} - -public class QuickTaskPreset -{ - public string Name { get; set; } - public List AfterCaptureTasks { get; set; } - public List AfterUploadTasks { get; set; } -} - -public class Theme -{ - public string Name { get; set; } - public string BackgroundColor { get; set; } - public string LightBackgroundColor { get; set; } - public string DarkBackgroundColor { get; set; } - public string TextColor { get; set; } - public string BorderColor { get; set; } - public string CheckerColor { get; set; } - public string CheckerColor2 { get; set; } - public int CheckerSize { get; set; } - public string LinkColor { get; set; } - public string MenuHighlightColor { get; set; } - public string MenuHighlightBorderColor { get; set; } - public string MenuBorderColor { get; set; } - public string MenuCheckBackgroundColor { get; set; } - public string MenuFont { get; set; } - public string ContextMenuFont { get; set; } - public int ContextMenuOpacity { get; set; } - public string SeparatorLightColor { get; set; } - public string SeparatorDarkColor { get; set; } -} - -public class ProxySettings -{ - public string ProxyMethod { get; set; } - public string Host { get; set; } - public int Port { get; set; } - public string Username { get; set; } - public string Password { get; set; } -} - -public class WindowState -{ - public string Location { get; set; } - public string Size { get; set; } - public bool IsMaximized { get; set; } -} - -public class ImageHistorySettings -{ - public bool RememberWindowState { get; set; } - public WindowState WindowState { get; set; } - public string ThumbnailSize { get; set; } - public int MaxItemCount { get; set; } - public bool FilterMissingFiles { get; set; } - public bool RememberSearchText { get; set; } - public string SearchText { get; set; } -} - -public class RootConfiguration -{ - public TaskSettings DefaultTaskSettings = TaskSettings.GetDefaultTaskSettings(); + public TaskSettings? DefaultTaskSettings = TaskSettings.GetDefaultTaskSettings(); public DateTime FirstTimeRunDate = DateTime.Now; public string FileUploadDefaultDirectory = ""; public int NameParserAutoIncrementNumber = 0; - public List QuickTaskPresets = []; + + public List QuickTaskPresets = QuickTaskInfo.DefaultPresets; // Main window public bool FirstTimeMinimizeToTray = true; public List TaskListViewColumnWidths = []; @@ -196,8 +38,8 @@ public class RootConfiguration // TEMP: For backward compatibility public bool CheckPreReleaseUpdates = false; public bool UseCustomTheme { get; set; } - public List Themes { get; set; } - public int SelectedTheme { get; set; } + public List Themes { get; set; } = Theme.GetDefaultThemes(); + public int SelectedTheme { get; set; } = 0; public bool UseCustomScreenshotsPath = false; public string? CustomScreenshotsPath = ""; public string? SaveImageSubFolderPattern = "%y-%mo"; @@ -224,7 +66,6 @@ public class RootConfiguration public List SecondaryFileUploaders = []; public bool HistorySaveTasks = true; public bool HistoryCheckURL = false; - public List RecentTasks { get; set; } public bool RecentTasksSave = false; public int RecentTasksMaxCount = 10; public bool RecentTasksShowInMainWindow = true; @@ -306,14 +147,8 @@ public bool DevMode [Category("Hotkey"), DefaultValue(500), Description("If you hold hotkeys then it will only trigger every this milliseconds.")] public int HotkeyRepeatLimit { - get - { - return hotkeyRepeatLimit; - } - set - { - hotkeyRepeatLimit = Math.Max(value, 200); - } + get => hotkeyRepeatLimit; + set => hotkeyRepeatLimit = Math.Max(value, 200); } [Category("Clipboard"), DefaultValue(true), Description("Show clipboard content viewer when using clipboard upload in main window.")] public bool ShowClipboardContentViewer { get; set; } @@ -362,10 +197,9 @@ public int HotkeyRepeatLimit [Category("Drag and drop window"), DefaultValue(255), Description("When you drag file to drop window then opacity will change to this.")] public int DropHoverOpacity { get; set; } - // [Category("Drag and drop window"), DefaultValue(ContentAlignment.BottomRight), Description("Where drop window will open.")] - // public ContentAlignment DropAlignment { get; set; } + [Category("Drag and drop window"), DefaultValue(ContentAlignment.BottomRight), Description("Where drop window will open.")] + public ContentAlignment DropAlignment { get; set; } public string ApplicationVersion { get; set; } = Helpers.GetApplicationVersion(); - public string? SQLitePath { get; set; } } diff --git a/SnapX.Core/Hotkey/HotkeyInfo.cs b/SnapX.Core/Hotkey/HotkeyInfo.cs index 592c1f0d0..7f10557bb 100644 --- a/SnapX.Core/Hotkey/HotkeyInfo.cs +++ b/SnapX.Core/Hotkey/HotkeyInfo.cs @@ -3,7 +3,7 @@ namespace SnapX.Core.Hotkey; -public class HotkeyInfo +public record HotkeyInfo() { public Keys Hotkey { get; set; } @@ -11,7 +11,7 @@ public class HotkeyInfo public ushort ID { get; set; } [JsonIgnore] - public HotkeyStatus Status { get; set; } + public HotkeyStatus Status { get; set; } = HotkeyStatus.NotConfigured; public Keys KeyCode => Hotkey & Keys.KeyCode; @@ -29,7 +29,7 @@ public Modifiers ModifiersEnum { get { - Modifiers modifiers = Modifiers.None; + var modifiers = Modifiers.None; if (Alt) modifiers |= Modifiers.Alt; if (Control) modifiers |= Modifiers.Control; @@ -44,11 +44,6 @@ public Modifiers ModifiersEnum public bool IsValidHotkey => KeyCode != Keys.None && !IsOnlyModifiers; - public HotkeyInfo() - { - Status = HotkeyStatus.NotConfigured; - } - public HotkeyInfo(Keys hotkey) : this() { Hotkey = hotkey; @@ -61,7 +56,7 @@ public HotkeyInfo(Keys hotkey, ushort id) : this(hotkey) public override string ToString() { - string text = ""; + var text = ""; if (Control) { @@ -107,13 +102,13 @@ public override string ToString() { text += "Scroll Lock"; } - else if (KeyCode >= Keys.D0 && KeyCode <= Keys.D9) + else if (KeyCode is >= Keys.D0 and <= Keys.D9) { text += (KeyCode - Keys.D0).ToString(); } - else if (KeyCode >= Keys.NumPad0 && KeyCode <= Keys.NumPad9) + else if (KeyCode is >= Keys.NumPad0 and <= Keys.NumPad9) { - text += "Numpad " + (KeyCode - Keys.NumPad0).ToString(); + text += "Numpad " + (KeyCode - Keys.NumPad0); } else { @@ -125,11 +120,11 @@ public override string ToString() private string ToStringWithSpaces(Keys key) { - string name = key.ToString(); + var name = key.ToString(); var result = new StringBuilder(); - for (int i = 0; i < name.Length; i++) + for (var i = 0; i < name.Length; i++) { if (i > 0 && char.IsUpper(name[i])) { diff --git a/SnapX.Core/Hotkey/HotkeySettings.cs b/SnapX.Core/Hotkey/HotkeySettings.cs index f34c189ba..7e431a0b9 100644 --- a/SnapX.Core/Hotkey/HotkeySettings.cs +++ b/SnapX.Core/Hotkey/HotkeySettings.cs @@ -5,16 +5,11 @@ using SnapX.Core.Job; namespace SnapX.Core.Hotkey; -public class HotkeySettings +public record HotkeySettings() { - public HotkeyInfo HotkeyInfo { get; set; } + public HotkeyInfo? HotkeyInfo { get; set; } = new(); - public TaskSettings TaskSettings { get; set; } - - public HotkeySettings() - { - HotkeyInfo = new HotkeyInfo(); - } + public TaskSettings? TaskSettings { get; set; } public HotkeySettings(HotkeyType job, Keys hotkey = Keys.None) : this() { @@ -27,7 +22,7 @@ public override string ToString() { if (HotkeyInfo != null && TaskSettings != null) { - return string.Format("Hotkey: {0}, Description: {1}, Job: {2}", HotkeyInfo, TaskSettings, TaskSettings.Job); + return $"Hotkey: {HotkeyInfo}, Description: {TaskSettings}, Job: {TaskSettings.Job}"; } return ""; diff --git a/SnapX.Core/Hotkey/HotkeysConfig.cs b/SnapX.Core/Hotkey/HotkeysConfig.cs index 72edba478..8baf56e7f 100644 --- a/SnapX.Core/Hotkey/HotkeysConfig.cs +++ b/SnapX.Core/Hotkey/HotkeysConfig.cs @@ -2,7 +2,7 @@ namespace SnapX.Core.Hotkey; -public class HotkeysConfig +public record HotkeysConfig { public List Hotkeys = HotkeyManager.GetDefaultHotkeyList(); } diff --git a/SnapX.Core/Media/GradientInfo.cs b/SnapX.Core/Media/GradientInfo.cs new file mode 100644 index 000000000..b65cfb6a9 --- /dev/null +++ b/SnapX.Core/Media/GradientInfo.cs @@ -0,0 +1,136 @@ +using System.ComponentModel; +using System.Text.Json.Serialization; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Drawing.Processing; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SnapX.Core.Utils; + +namespace SnapX.Core.Media; + +public enum LinearGradientMode +{ + Horizontal, + Vertical +} + +public record GradientStop(Color Color, float Location) +{ + public Color Color { get; set; } = Color; + public float Location { get; set; } = Location; // 0-100 +} + +public class GradientInfo(LinearGradientMode Type) +{ + [DefaultValue(LinearGradientMode.Vertical)] + public LinearGradientMode Type { get; set; } = Type; + + /// + /// Gradient color stops, each with a Ratio in [0,1] + /// + public List Colors { get; set; } = new(); + + [JsonIgnore] + public bool IsValid => Colors is { Count: > 0 }; + + [JsonIgnore] + public bool IsVisible => IsValid && Colors.Any(x => x.Color.ToPixel().A > 0); + + [JsonIgnore] + public bool IsTransparent => IsValid && Colors.Any(x => x.Color.ToPixel().A < 255); + + public GradientInfo() : this(LinearGradientMode.Vertical) { } + + public GradientInfo(LinearGradientMode type, params ColorStop[] colors) : this(type) + { + Colors = colors.ToList(); + } + + public GradientInfo(LinearGradientMode type, params Color[] colors) : this(type) + { + var count = colors.Length; + for (var i = 0; i < count; i++) + { + var ratio = (count == 1) ? 0f : i / (float)(count - 1); + Colors.Add(new ColorStop(ratio, colors[i])); + } + } + + public GradientInfo(params ColorStop[] colors) : this(LinearGradientMode.Vertical, colors) { } + + public GradientInfo(params Color[] colors) : this(LinearGradientMode.Vertical, colors) { } + + public void Clear() + { + Colors.Clear(); + } + + public void Sort() + { + Colors.Sort((x, y) => x.Ratio.CompareTo(y.Ratio)); + } + + public void Reverse() + { + Colors = Colors + .Select(s => new ColorStop(1f - s.Ratio, s.Color)) + .OrderBy(s => s.Ratio) + .ToList(); + } + + /// + /// Returns an ImageSharp LinearGradientBrush based on this gradient info. + /// + public Brush GetGradientBrush(RectangleF rect) + { + var stops = Colors + .OrderBy(x => x.Ratio) + .ToArray(); + + if (stops.All(x => x.Ratio != 0f)) + { + var first = stops.FirstOrDefault(); + stops = new[] { new ColorStop(0f, first.Color) }.Concat(stops).ToArray(); + } + + if (stops.All(x => x.Ratio != 1f)) + { + var last = stops.LastOrDefault(); + stops = stops.Append(new ColorStop(1f, last.Color)).ToArray(); + } + + var start = new PointF(rect.Left, rect.Top); + + var end = Type == LinearGradientMode.Horizontal + ? new PointF(rect.Right, rect.Top) + : new PointF(rect.Left, rect.Bottom); + + return new LinearGradientBrush(start, end, GradientRepetitionMode.Repeat, stops); + } + + public Image CreateGradientPreview(int width, int height, bool border = false, bool checkers = false) + { + var image = new Image(width, height); + + if (checkers && IsTransparent) + { + ImageHelpers.DrawCheckerPattern(image, 10, [Color.LightGray, Color.White]); + } + + var brush = GetGradientBrush(new RectangleF(0, 0, width, height)); + + image.Mutate(ctx => + { + ctx.Fill(brush); + + if (border) + { + ctx.Draw(Color.Black, 1, new RectangleF(0, 0, width - 1, height - 1)); + } + }); + + return image; + } + + public override string ToString() => "Gradient"; +} diff --git a/SnapX.Core/ScreenCapture/RegionCaptureOptions.cs b/SnapX.Core/SharpCapture/RegionCaptureOptions.cs similarity index 87% rename from SnapX.Core/ScreenCapture/RegionCaptureOptions.cs rename to SnapX.Core/SharpCapture/RegionCaptureOptions.cs index 4a2a7eac4..34094c5d1 100644 --- a/SnapX.Core/ScreenCapture/RegionCaptureOptions.cs +++ b/SnapX.Core/SharpCapture/RegionCaptureOptions.cs @@ -3,10 +3,11 @@ using SixLabors.ImageSharp; +using SnapX.Core.History; using SnapX.Core.ImageEffects; -using SnapX.Core.ScreenCapture.Helpers; +using SnapX.Core.SharpCapture.Helpers; -namespace SnapX.Core.ScreenCapture; +namespace SnapX.Core.SharpCapture; public class RegionCaptureOptions { @@ -34,16 +35,20 @@ public class RegionCaptureOptions public string CustomInfoText = "X: $x, Y: $y$nR: $r, G: $g, B: $b$nHex: $hex"; // Formats: $x, $y, $r, $g, $b, $hex, $HEX, $n public List SnapSizes = [ - new(426, 240), // 240p - new(640, 360), // 360p - new(854, 480), // 480p - new(1280, 720), // 720p - new(1920, 1080) // 1080p + new(426, 240), // 240p + new(640, 360), // 360p + new(854, 480), // 480p + new(1280, 720), // 720p + new(1920, 1080), // 1080p + new(2560, 1440), // 1440p + new(3840, 2160), // 2160p + new(5120, 2880), // 2880p / 5K + new(7680, 4320) // 4320p / 8K ]; public bool ShowInfo = true; public bool ShowMagnifier = true; public bool UseSquareMagnifier = false; - public int MagnifierPixelCount = 15; // Must be odd number like 11, 13, 15 etc. + public int MagnifierPixelCount = 15; // Must be odd number like 11, 13, 15, etc. public int MagnifierPixelSize = 10; public bool ShowCrosshair = false; public bool UseLightResizeNodes = false; @@ -76,7 +81,7 @@ public class RegionCaptureOptions public bool AutoCloseEditorOnTask = false; public bool ShowEditorPanTip = true; public ImageInterpolationMode ImageEditorResizeInterpolationMode = ImageInterpolationMode.Bicubic; - public Size EditorNewImageSize = new Size(800, 600); + public Size EditorNewImageSize = new(800, 600); public bool EditorNewImageTransparent = false; public Color EditorNewImageBackgroundColor = Color.White; public Color EditorCanvasColor = Color.Transparent; diff --git a/SnapX.Core/SharpCapture/ScreenRecording/ScreenRecordingOptions.cs b/SnapX.Core/SharpCapture/ScreenRecording/ScreenRecordingOptions.cs index 9989fbd32..df835b37e 100644 --- a/SnapX.Core/SharpCapture/ScreenRecording/ScreenRecordingOptions.cs +++ b/SnapX.Core/SharpCapture/ScreenRecording/ScreenRecordingOptions.cs @@ -6,7 +6,7 @@ using System.Text; using SixLabors.ImageSharp; -namespace SnapX.Core.ScreenCapture.ScreenRecording; +namespace SnapX.Core.SharpCapture.ScreenRecording; public class ScreenRecordingOptions { diff --git a/SnapX.Core/SnapXResources.cs b/SnapX.Core/SnapXResources.cs index 144f5a51b..c7d080abe 100644 --- a/SnapX.Core/SnapXResources.cs +++ b/SnapX.Core/SnapXResources.cs @@ -2,8 +2,12 @@ // SPDX-License-Identifier: GPL-3.0-or-later +using System.ComponentModel; using System.Runtime.InteropServices; +using SixLabors.ImageSharp; using SnapX.Core.Utils; +using SnapX.Core.Utils.Converters; +using SnapX.Core.Utils.Extensions; using SnapX.Core.Utils.Miscellaneous; namespace SnapX.Core; @@ -17,3 +21,238 @@ public static class SnapXResources public static string fancyOsName => Helpers.GetOperatingSystemProductName(); public static string UserAgent => $"{SnapX.AppName}/{Helpers.GetApplicationVersion()} (+{Links.GitHub})"; } + + +public class Theme +{ + public string Name { get; set; } = "Dark"; + + private Color backgroundColor; + + [TypeConverter(typeof(MyColorConverter))] + public Color BackgroundColor + { + get => backgroundColor; + set + { + if (!value.IsTransparent()) backgroundColor = value; + } + } + + private Color lightBackgroundColor; + + [TypeConverter(typeof(MyColorConverter))] + public Color LightBackgroundColor + { + get => lightBackgroundColor; + set + { + if (!value.IsTransparent()) lightBackgroundColor = value; + } + } + + private Color darkBackgroundColor; + + [TypeConverter(typeof(MyColorConverter))] + public Color DarkBackgroundColor + { + get => darkBackgroundColor; + set + { + if (!value.IsTransparent()) darkBackgroundColor = value; + } + } + + private Color textColor; + + [TypeConverter(typeof(MyColorConverter))] + public Color TextColor + { + get => textColor; + set + { + if (!value.IsTransparent()) textColor = value; + } + } + + private Color borderColor; + + [TypeConverter(typeof(MyColorConverter))] + public Color BorderColor + { + get => borderColor; + set + { + if (!value.IsTransparent()) borderColor = value; + } + } + + [TypeConverter(typeof(MyColorConverter))] + public Color CheckerColor { get; set; } + + [TypeConverter(typeof(MyColorConverter))] + public Color CheckerColor2 { get; set; } + + public int CheckerSize { get; set; } = 15; + + [TypeConverter(typeof(MyColorConverter))] + public Color LinkColor { get; set; } + + [TypeConverter(typeof(MyColorConverter))] + public Color MenuHighlightColor { get; set; } + + [TypeConverter(typeof(MyColorConverter))] + public Color MenuHighlightBorderColor { get; set; } + + [TypeConverter(typeof(MyColorConverter))] + public Color MenuBorderColor { get; set; } + + [TypeConverter(typeof(MyColorConverter))] + public Color MenuCheckBackgroundColor { get; set; } + public record UIFont(string Name, float Size); + public UIFont MenuFont { get; set; } = new("Inter", 11f); + + public UIFont ContextMenuFont { get; set; } = new("Inter", 11f); + + public int ContextMenuOpacity { get; set; } = 100; + + [Browsable(false)] + public double ContextMenuOpacityDouble => ContextMenuOpacity.Clamp(10, 100) / 100d; + + [TypeConverter(typeof(MyColorConverter))] + public Color SeparatorLightColor { get; set; } + + [TypeConverter(typeof(MyColorConverter))] + public Color SeparatorDarkColor { get; set; } + + [Browsable(false)] + public bool IsDarkTheme => ColorHelpers.IsDarkColor(BackgroundColor); + + + public static Theme DarkTheme => new() + { + Name = "Dark", + BackgroundColor = Color.FromRgba(39, 39, 39, 255), + LightBackgroundColor = Color.FromRgba(46, 46, 46, 255), + DarkBackgroundColor = Color.FromRgba(34, 34, 34, 255), + TextColor = Color.FromRgba(231, 233, 234, 255), + BorderColor = Color.FromRgba(31, 31, 31, 255), + CheckerColor = Color.FromRgba(46, 46, 46, 255), + CheckerColor2 = Color.FromRgba(39, 39, 39, 255), + LinkColor = Color.FromRgba(166, 212, 255, 255), + MenuHighlightColor = Color.FromRgba(46, 46, 46, 255), + MenuHighlightBorderColor = Color.FromRgba(63, 63, 63, 255), + MenuBorderColor = Color.FromRgba(63, 63, 63, 255), + MenuCheckBackgroundColor = Color.FromRgba(51, 51, 51, 255), + SeparatorLightColor = Color.FromRgba(44, 44, 44, 255), + SeparatorDarkColor = Color.FromRgba(31, 31, 31, 255) + }; + + public static Theme LightTheme => new() + { + Name = "Light", + BackgroundColor = Color.FromRgba(242, 242, 242, 255), + LightBackgroundColor = Color.FromRgba(247, 247, 247, 255), + DarkBackgroundColor = Color.FromRgba(235, 235, 235, 255), + TextColor = Color.FromRgba(69, 69, 69, 255), + BorderColor = Color.FromRgba(201, 201, 201, 255), + CheckerColor = Color.FromRgba(247, 247, 247, 255), + CheckerColor2 = Color.FromRgba(235, 235, 235, 255), + LinkColor = Color.FromRgba(166, 212, 255, 255), + MenuHighlightColor = Color.FromRgba(247, 247, 247, 255), + MenuHighlightBorderColor = Color.FromRgba(96, 143, 226, 255), + MenuBorderColor = Color.FromRgba(201, 201, 201, 255), + MenuCheckBackgroundColor = Color.FromRgba(225, 233, 244, 255), + SeparatorLightColor = Color.FromRgba(253, 253, 253, 255), + SeparatorDarkColor = Color.FromRgba(189, 189, 189, 255) + }; + + public static Theme NightTheme => new() + { + Name = "Night", + BackgroundColor = Color.FromRgba(42, 47, 56, 255), + LightBackgroundColor = Color.FromRgba(52, 57, 65, 255), + DarkBackgroundColor = Color.FromRgba(28, 32, 38, 255), + TextColor = Color.FromRgba(235, 235, 235, 255), + BorderColor = Color.FromRgba(28, 32, 38, 255), + CheckerColor = Color.FromRgba(60, 60, 60, 255), + CheckerColor2 = Color.FromRgba(50, 50, 50, 255), + LinkColor = Color.FromRgba(166, 212, 255, 255), + MenuHighlightColor = Color.FromRgba(30, 34, 40, 255), + MenuHighlightBorderColor = Color.FromRgba(116, 129, 152, 255), + MenuBorderColor = Color.FromRgba(22, 26, 31, 255), + MenuCheckBackgroundColor = Color.FromRgba(56, 64, 75, 255), + SeparatorLightColor = Color.FromRgba(56, 64, 75, 255), + SeparatorDarkColor = Color.FromRgba(22, 26, 31, 255) + }; + + // https://www.nordtheme.com + public static Theme NordDarkTheme => new() + { + Name = "Nord Dark", + BackgroundColor = Color.FromRgba(46, 52, 64, 255), + LightBackgroundColor = Color.FromRgba(59, 66, 82, 255), + DarkBackgroundColor = Color.FromRgba(38, 44, 57, 255), + TextColor = Color.FromRgba(229, 233, 240, 255), + BorderColor = Color.FromRgba(30, 38, 54, 255), + CheckerColor = Color.FromRgba(46, 52, 64, 255), + CheckerColor2 = Color.FromRgba(36, 42, 54, 255), + LinkColor = Color.FromRgba(136, 192, 208, 255), + MenuHighlightColor = Color.FromRgba(36, 42, 54, 255), + MenuHighlightBorderColor = Color.FromRgba(24, 30, 42, 255), + MenuBorderColor = Color.FromRgba(24, 30, 42, 255), + MenuCheckBackgroundColor = Color.FromRgba(59, 66, 82, 255), + SeparatorLightColor = Color.FromRgba(59, 66, 82, 255), + SeparatorDarkColor = Color.FromRgba(30, 38, 54, 255) + }; + + // https://www.nordtheme.com + public static Theme NordLightTheme => new() + { + Name = "Nord Light", + BackgroundColor = Color.FromRgba(229, 233, 240, 255), + LightBackgroundColor = Color.FromRgba(236, 239, 244, 255), + DarkBackgroundColor = Color.FromRgba(216, 222, 233, 255), + TextColor = Color.FromRgba(59, 66, 82, 255), + BorderColor = Color.FromRgba(207, 216, 233, 255), + CheckerColor = Color.FromRgba(229, 233, 240, 255), + CheckerColor2 = Color.FromRgba(216, 222, 233, 255), + LinkColor = Color.FromRgba(106, 162, 178, 255), + MenuHighlightColor = Color.FromRgba(236, 239, 244, 255), + MenuHighlightBorderColor = Color.FromRgba(207, 216, 233, 255), + MenuBorderColor = Color.FromRgba(216, 222, 233, 255), + MenuCheckBackgroundColor = Color.FromRgba(229, 233, 240, 255), + SeparatorLightColor = Color.FromRgba(236, 239, 244, 255), + SeparatorDarkColor = Color.FromRgba(207, 216, 233, 255) + }; + + // https://draculatheme.com + public static Theme DraculaTheme => new() + { + Name = "Dracula", + BackgroundColor = Color.FromRgba(40, 42, 54, 255), + LightBackgroundColor = Color.FromRgba(68, 71, 90, 255), + DarkBackgroundColor = Color.FromRgba(36, 38, 48, 255), + TextColor = Color.FromRgba(248, 248, 242, 255), + BorderColor = Color.FromRgba(33, 35, 43, 255), + CheckerColor = Color.FromRgba(40, 42, 54, 255), + CheckerColor2 = Color.FromRgba(36, 38, 48, 255), + LinkColor = Color.FromRgba(98, 114, 164, 255), + MenuHighlightColor = Color.FromRgba(36, 38, 48, 255), + MenuHighlightBorderColor = Color.FromRgba(255, 121, 198, 255), + MenuBorderColor = Color.FromRgba(33, 35, 43, 255), + MenuCheckBackgroundColor = Color.FromRgba(45, 47, 61, 255), + SeparatorLightColor = Color.FromRgba(45, 47, 61, 255), + SeparatorDarkColor = Color.FromRgba(33, 35, 43, 255) + }; + + public static List GetDefaultThemes() + { + return [DarkTheme, LightTheme, NightTheme, NordDarkTheme, NordLightTheme, DraculaTheme]; + } + + public override string ToString() + { + return Name; + } +} diff --git a/SnapX.Core/Utils/Extensions/Extensions.cs b/SnapX.Core/Utils/Extensions/Extensions.cs index ebefe6a73..68c5661ab 100644 --- a/SnapX.Core/Utils/Extensions/Extensions.cs +++ b/SnapX.Core/Utils/Extensions/Extensions.cs @@ -6,6 +6,7 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; namespace SnapX.Core.Utils.Extensions; @@ -229,7 +230,10 @@ public static List Range(this List source, T start, T end) return Range(source, startIndex, endIndex); } - public static bool IsTransparent(this Color color) => color.IsTransparent(); + public static bool IsTransparent(this Color color) + { + return color.ToPixel().A < 255; + } public static string ToStringProper(this Rectangle rect) => $"X: {rect.X}, Y: {rect.Y}, Width: {rect.Width}, Height: {rect.Height}"; } From 857f67a20e73447ff87d238cd3a95be4251f1b2a Mon Sep 17 00:00:00 2001 From: Brycen G Date: Fri, 11 Jul 2025 19:56:40 -0400 Subject: [PATCH 09/31] chore(Core): move all ScreenCapture classes to SharpCapture namespace --- SnapX.Core/Capture/CaptureActiveMonitor.cs | 22 -- SnapX.Core/Capture/CaptureActiveWindow.cs | 25 -- SnapX.Core/Capture/CaptureBase.cs | 124 ------- SnapX.Core/Capture/CaptureCustomRegion.cs | 19 - SnapX.Core/Capture/CaptureCustomWindow.cs | 34 -- SnapX.Core/Capture/CaptureFullscreen.cs | 21 -- SnapX.Core/Capture/CaptureLastRegion.cs | 21 -- SnapX.Core/Capture/CaptureMonitor.cs | 26 -- SnapX.Core/Capture/CaptureWindow.cs | 53 --- .../SharpCapture/Animations/BaseAnimation.cs | 2 +- .../Animations/ColorBlinkAnimation.cs | 2 +- .../Animations/OpacityAnimation.cs | 2 +- .../SharpCapture/Animations/PointAnimation.cs | 2 +- .../Animations/RectangleAnimation.cs | 2 +- .../SharpCapture/Animations/TextAnimation.cs | 2 +- .../{BaseCapture.cs => BaseSharpCapture.cs} | 14 +- .../SharpCapture/CaptureActiveMonitor.cs | 36 ++ .../SharpCapture/CaptureActiveWindow.cs | 33 ++ SnapX.Core/SharpCapture/CaptureBase.cs | 146 ++++++++ .../SharpCapture/CaptureCustomRegion.cs | 21 ++ .../SharpCapture/CaptureCustomWindow.cs | 35 ++ SnapX.Core/SharpCapture/CaptureFullscreen.cs | 27 ++ SnapX.Core/SharpCapture/CaptureLastRegion.cs | 27 ++ SnapX.Core/SharpCapture/CaptureMonitor.cs | 28 ++ .../CaptureRegion.cs | 48 ++- SnapX.Core/SharpCapture/CaptureWindow.cs | 49 +++ .../{ScreenCapture => SharpCapture}/Enums.cs | 2 +- .../SharpCapture/Helpers/InputManager.cs | 2 +- .../SharpCapture/Helpers/LocationInfo.cs | 2 +- .../SharpCapture/Helpers/SimpleWindowInfo.cs | 2 +- SnapX.Core/SharpCapture/Helpers/SnapSize.cs | 2 +- .../SharpCapture/Helpers/WindowsList.cs | 2 +- .../Interfaces/ICaptureService.cs | 12 + .../SharpCapture/Linux/DBus/DesktopDBus.cs | 326 ------------------ .../Linux/DBus/PropertyChanges.cs | 10 +- SnapX.Core/SharpCapture/Linux/LinuxCapture.cs | 13 +- .../RegionCaptureTasks.cs | 4 +- .../ScreenRecording/FFmpegCaptureDevice.cs | 2 +- .../ScreenRecording/FFmpegOptions.cs | 2 +- .../ScreenRecording/HardDiskCache.cs | 4 +- .../ScreenRecording/ImageCache.cs | 2 +- .../ScreenRecording/ScreenRecorder.cs | 2 +- .../SharpCapture/Services/CaptureService.cs | 32 ++ SnapX.Core/SharpCapture/macOS/macOSCapture.cs | 13 +- 44 files changed, 515 insertions(+), 740 deletions(-) delete mode 100644 SnapX.Core/Capture/CaptureActiveMonitor.cs delete mode 100644 SnapX.Core/Capture/CaptureActiveWindow.cs delete mode 100644 SnapX.Core/Capture/CaptureBase.cs delete mode 100644 SnapX.Core/Capture/CaptureCustomRegion.cs delete mode 100644 SnapX.Core/Capture/CaptureCustomWindow.cs delete mode 100644 SnapX.Core/Capture/CaptureFullscreen.cs delete mode 100644 SnapX.Core/Capture/CaptureLastRegion.cs delete mode 100644 SnapX.Core/Capture/CaptureMonitor.cs delete mode 100644 SnapX.Core/Capture/CaptureWindow.cs rename SnapX.Core/SharpCapture/{BaseCapture.cs => BaseSharpCapture.cs} (72%) create mode 100644 SnapX.Core/SharpCapture/CaptureActiveMonitor.cs create mode 100644 SnapX.Core/SharpCapture/CaptureActiveWindow.cs create mode 100644 SnapX.Core/SharpCapture/CaptureBase.cs create mode 100644 SnapX.Core/SharpCapture/CaptureCustomRegion.cs create mode 100644 SnapX.Core/SharpCapture/CaptureCustomWindow.cs create mode 100644 SnapX.Core/SharpCapture/CaptureFullscreen.cs create mode 100644 SnapX.Core/SharpCapture/CaptureLastRegion.cs create mode 100644 SnapX.Core/SharpCapture/CaptureMonitor.cs rename SnapX.Core/{Capture => SharpCapture}/CaptureRegion.cs (77%) create mode 100644 SnapX.Core/SharpCapture/CaptureWindow.cs rename SnapX.Core/{ScreenCapture => SharpCapture}/Enums.cs (99%) create mode 100644 SnapX.Core/SharpCapture/Interfaces/ICaptureService.cs rename SnapX.Core/{ScreenCapture => SharpCapture}/RegionCaptureTasks.cs (98%) create mode 100644 SnapX.Core/SharpCapture/Services/CaptureService.cs diff --git a/SnapX.Core/Capture/CaptureActiveMonitor.cs b/SnapX.Core/Capture/CaptureActiveMonitor.cs deleted file mode 100644 index 5048d21b1..000000000 --- a/SnapX.Core/Capture/CaptureActiveMonitor.cs +++ /dev/null @@ -1,22 +0,0 @@ - -// SPDX-License-Identifier: GPL-3.0-or-later - - -using SnapX.Core.Job; - -namespace SnapX.Core.Capture; - -public class CaptureActiveMonitor : CaptureBase -{ - protected override TaskMetadata Execute(TaskSettings taskSettings) - { - DebugHelper.WriteLine("CaptureActiveMonitor started"); - var promise = TaskHelpers.GetScreenshot(taskSettings).CaptureActiveMonitor(); - promise.Wait(); - var img = promise.Result; - var metadata = CreateMetadata(img.Bounds); - metadata.Image = img; - return metadata; - } -} - diff --git a/SnapX.Core/Capture/CaptureActiveWindow.cs b/SnapX.Core/Capture/CaptureActiveWindow.cs deleted file mode 100644 index 92dd8d7a8..000000000 --- a/SnapX.Core/Capture/CaptureActiveWindow.cs +++ /dev/null @@ -1,25 +0,0 @@ - -// SPDX-License-Identifier: GPL-3.0-or-later - - -using SnapX.Core.Job; - -namespace SnapX.Core.Capture; -public class CaptureActiveWindow : CaptureBase -{ - protected override TaskMetadata Execute(TaskSettings taskSettings) - { - var metadata = CreateMetadata(); - - if (taskSettings.CaptureSettings.CaptureTransparent && !taskSettings.CaptureSettings.CaptureClientArea) - { - metadata.Image = TaskHelpers.GetScreenshot(taskSettings).CaptureActiveWindowTransparent(); - } - else - { - metadata.Image = TaskHelpers.GetScreenshot(taskSettings).CaptureActiveWindow(); - } - - return metadata; - } -} diff --git a/SnapX.Core/Capture/CaptureBase.cs b/SnapX.Core/Capture/CaptureBase.cs deleted file mode 100644 index ceb1dca8c..000000000 --- a/SnapX.Core/Capture/CaptureBase.cs +++ /dev/null @@ -1,124 +0,0 @@ - -// SPDX-License-Identifier: GPL-3.0-or-later - - -using SixLabors.ImageSharp; -using SnapX.Core.Job; -using SnapX.Core.Upload; -using SnapX.Core.Utils.Extensions; -using SnapX.Core.Utils.Native; - -namespace SnapX.Core.Capture; -public abstract class CaptureBase -{ - public bool AllowAutoHideForm { get; set; } = true; - public bool AllowAnnotation { get; set; } = true; - - public void Capture(bool autoHideForm) - { - Capture(null, autoHideForm); - } - - public void Capture(TaskSettings taskSettings = null, bool autoHideForm = false) - { - if (taskSettings == null) taskSettings = TaskSettings.GetDefaultTaskSettings(); - - // TODO: Reimplement taskSettings.GeneralSettings.ToastWindowAutoHide - // if (taskSettings.GeneralSettings.ToastWindowAutoHide) - // { - // NotificationForm.CloseActiveForm(); - // } - - if (taskSettings.CaptureSettings.ScreenshotDelay > 0) - { - int delay = (int)(taskSettings.CaptureSettings.ScreenshotDelay * 1000); - - Task.Delay(delay).ContinueInCurrentContext(() => - { - CaptureInternal(taskSettings, autoHideForm); - }); - } - else - { - CaptureInternal(taskSettings, autoHideForm); - } - } - - protected abstract TaskMetadata Execute(TaskSettings taskSettings); - - private void CaptureInternal(TaskSettings taskSettings, bool autoHideForm) - { - if (autoHideForm && AllowAutoHideForm) - { - // SnapX.MainWindow.Hide(); - // Thread.Sleep(250); - } - - TaskMetadata metadata = null; - - try - { - AllowAnnotation = true; - metadata = Execute(taskSettings); - } - catch (Exception ex) - { - DebugHelper.WriteException(ex); - } - finally - { - if (autoHideForm && AllowAutoHideForm) - { - // SnapX.MainWindow.ForceActivate(); - } - - AfterCapture(metadata, taskSettings); - } - } - - private void AfterCapture(TaskMetadata metadata, TaskSettings taskSettings) - { - if (metadata != null && metadata.Image != null) - { - TaskHelpers.PlayNotificationSoundAsync(NotificationSound.Capture, taskSettings); - - if (taskSettings.AfterCaptureJob.HasFlag(AfterCaptureTasks.AnnotateImage) && !AllowAnnotation) - { - taskSettings.AfterCaptureJob = taskSettings.AfterCaptureJob.Remove(AfterCaptureTasks.AnnotateImage); - } - - if (taskSettings.ImageSettings.ImageEffectOnlyRegionCapture && - GetType() != typeof(CaptureRegion) && GetType() != typeof(CaptureLastRegion)) - { - taskSettings.AfterCaptureJob = taskSettings.AfterCaptureJob.Remove(AfterCaptureTasks.AddImageEffects); - } - - UploadManager.RunImageTask(metadata, taskSettings); - } - } - - protected TaskMetadata CreateMetadata() - { - return CreateMetadata(Rectangle.Empty, null); - } - - protected TaskMetadata CreateMetadata(Rectangle insideRect) - { - return CreateMetadata(insideRect, "explorer"); - } - - protected TaskMetadata CreateMetadata(Rectangle insideRect, string ignoreProcess) - { - var metadata = new TaskMetadata(); - - var windowInfo = Methods.GetForegroundWindow(); - if ((ignoreProcess == null || !windowInfo.ProcessName.Equals(ignoreProcess, StringComparison.OrdinalIgnoreCase)) && - (insideRect.IsEmpty || windowInfo.Rectangle.Contains(insideRect))) - { - metadata.UpdateInfo(windowInfo); - } - - return metadata; - } -} - diff --git a/SnapX.Core/Capture/CaptureCustomRegion.cs b/SnapX.Core/Capture/CaptureCustomRegion.cs deleted file mode 100644 index 712481ca4..000000000 --- a/SnapX.Core/Capture/CaptureCustomRegion.cs +++ /dev/null @@ -1,19 +0,0 @@ - -// SPDX-License-Identifier: GPL-3.0-or-later - - -using SnapX.Core.Job; - -namespace SnapX.Core.Capture; - -public class CaptureCustomRegion : CaptureBase -{ - protected override TaskMetadata Execute(TaskSettings taskSettings) - { - var rect = taskSettings.CaptureSettings.CaptureCustomRegion; - var metadata = CreateMetadata(rect); - metadata.Image = TaskHelpers.GetScreenshot(taskSettings).CaptureRectangle(rect); - return metadata; - } -} - diff --git a/SnapX.Core/Capture/CaptureCustomWindow.cs b/SnapX.Core/Capture/CaptureCustomWindow.cs deleted file mode 100644 index 6cafe2558..000000000 --- a/SnapX.Core/Capture/CaptureCustomWindow.cs +++ /dev/null @@ -1,34 +0,0 @@ - -// SPDX-License-Identifier: GPL-3.0-or-later - - -using SnapX.Core.Job; - -namespace SnapX.Core.Capture; -public class CaptureCustomWindow : CaptureWindow -{ - protected override TaskMetadata Execute(TaskSettings taskSettings) - { - string windowTitle = taskSettings.CaptureSettings.CaptureCustomWindow; - - if (!string.IsNullOrEmpty(windowTitle)) - { - // TODO: Reimplement w/ Windows support & Linux (X11, and KDE Plasma Wayland) - // IntPtr hWnd = NativeMethods.SearchWindow(windowTitle); - // - // if (hWnd == IntPtr.Zero) - // { - // MessageBox.Show(Resources.UnableToFindAWindowWithSpecifiedWindowTitle, "SnapX", MessageBoxButtons.OK, MessageBoxIcon.Information); - // } - // else - // { - // WindowHandle = hWnd; - // - // return base.Execute(taskSettings); - // } - } - - return null; - } -} - diff --git a/SnapX.Core/Capture/CaptureFullscreen.cs b/SnapX.Core/Capture/CaptureFullscreen.cs deleted file mode 100644 index 9e1e5f8a8..000000000 --- a/SnapX.Core/Capture/CaptureFullscreen.cs +++ /dev/null @@ -1,21 +0,0 @@ - -// SPDX-License-Identifier: GPL-3.0-or-later - - -using SnapX.Core.Job; - -namespace SnapX.Core.Capture; - -public class CaptureFullscreen : CaptureBase -{ - protected override TaskMetadata Execute(TaskSettings taskSettings) - { - DebugHelper.WriteLine("CaptureFullscreen"); - var img = TaskHelpers.GetScreenshot(taskSettings).CaptureFullscreen(); - var metadata = CreateMetadata(img.Bounds); - metadata.Image = img; - - return metadata; - } -} - diff --git a/SnapX.Core/Capture/CaptureLastRegion.cs b/SnapX.Core/Capture/CaptureLastRegion.cs deleted file mode 100644 index b99455790..000000000 --- a/SnapX.Core/Capture/CaptureLastRegion.cs +++ /dev/null @@ -1,21 +0,0 @@ - -// SPDX-License-Identifier: GPL-3.0-or-later - - -using SnapX.Core.Job; - -namespace SnapX.Core.Capture; -public class CaptureLastRegion : CaptureRegion -{ - protected override TaskMetadata Execute(TaskSettings taskSettings) - { - switch (lastRegionCaptureType) - { - default: - case RegionCaptureType.Default: return ExecuteRegionCapture(taskSettings); - case RegionCaptureType.Light: return ExecuteRegionCaptureLight(taskSettings); - case RegionCaptureType.Transparent: return ExecuteRegionCaptureTransparent(taskSettings); - } - } -} - diff --git a/SnapX.Core/Capture/CaptureMonitor.cs b/SnapX.Core/Capture/CaptureMonitor.cs deleted file mode 100644 index 25ebb0fc4..000000000 --- a/SnapX.Core/Capture/CaptureMonitor.cs +++ /dev/null @@ -1,26 +0,0 @@ - -// SPDX-License-Identifier: GPL-3.0-or-later - - -using SixLabors.ImageSharp; -using SnapX.Core.Job; - -namespace SnapX.Core.Capture; -public class CaptureMonitor : CaptureBase -{ - public Rectangle MonitorRectangle { get; private set; } - - public CaptureMonitor(Rectangle monitorRectangle) - { - MonitorRectangle = monitorRectangle; - } - - protected override TaskMetadata Execute(TaskSettings taskSettings) - { - DebugHelper.WriteLine("CaptureMonitor Start"); - var metadata = CreateMetadata(MonitorRectangle); - metadata.Image = TaskHelpers.GetScreenshot().CaptureRectangle(MonitorRectangle); - return metadata; - } -} - diff --git a/SnapX.Core/Capture/CaptureWindow.cs b/SnapX.Core/Capture/CaptureWindow.cs deleted file mode 100644 index b6f0927f6..000000000 --- a/SnapX.Core/Capture/CaptureWindow.cs +++ /dev/null @@ -1,53 +0,0 @@ - -// SPDX-License-Identifier: GPL-3.0-or-later - - -using SnapX.Core.Job; -using SnapX.Core.Media; - -namespace SnapX.Core.Capture; -public class CaptureWindow : CaptureBase -{ - public IntPtr WindowHandle { get; protected set; } - - public CaptureWindow() - { - } - - public CaptureWindow(IntPtr windowHandle) - { - WindowHandle = windowHandle; - } - - protected override TaskMetadata Execute(TaskSettings taskSettings) - { - WindowInfo windowInfo = new(WindowHandle); - - if (windowInfo.IsMinimized) - { - windowInfo.Restore(); - Thread.Sleep(250); - } - - if (!windowInfo.IsActive) - { - windowInfo.Activate(); - Thread.Sleep(100); - } - - var metadata = new TaskMetadata(); - metadata.UpdateInfo(windowInfo); - - if (taskSettings.CaptureSettings.CaptureTransparent && !taskSettings.CaptureSettings.CaptureClientArea) - { - metadata.Image = TaskHelpers.GetScreenshot(taskSettings).CaptureWindowTransparent(WindowHandle); - } - else - { - metadata.Image = TaskHelpers.GetScreenshot(taskSettings).CaptureWindow(WindowHandle); - } - - return metadata; - } -} - diff --git a/SnapX.Core/SharpCapture/Animations/BaseAnimation.cs b/SnapX.Core/SharpCapture/Animations/BaseAnimation.cs index f4fa50d87..45839a27c 100644 --- a/SnapX.Core/SharpCapture/Animations/BaseAnimation.cs +++ b/SnapX.Core/SharpCapture/Animations/BaseAnimation.cs @@ -4,7 +4,7 @@ using System.Diagnostics; -namespace SnapX.Core.ScreenCapture.Animations; +namespace SnapX.Core.SharpCapture.Animations; internal class BaseAnimation { diff --git a/SnapX.Core/SharpCapture/Animations/ColorBlinkAnimation.cs b/SnapX.Core/SharpCapture/Animations/ColorBlinkAnimation.cs index 472299490..aebb91213 100644 --- a/SnapX.Core/SharpCapture/Animations/ColorBlinkAnimation.cs +++ b/SnapX.Core/SharpCapture/Animations/ColorBlinkAnimation.cs @@ -5,7 +5,7 @@ using SixLabors.ImageSharp; using SnapX.Core.Utils; -namespace SnapX.Core.ScreenCapture.Animations; +namespace SnapX.Core.SharpCapture.Animations; internal class ColorBlinkAnimation : BaseAnimation { diff --git a/SnapX.Core/SharpCapture/Animations/OpacityAnimation.cs b/SnapX.Core/SharpCapture/Animations/OpacityAnimation.cs index 33ad1e598..5062e1dc1 100644 --- a/SnapX.Core/SharpCapture/Animations/OpacityAnimation.cs +++ b/SnapX.Core/SharpCapture/Animations/OpacityAnimation.cs @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later -namespace SnapX.Core.ScreenCapture.Animations; +namespace SnapX.Core.SharpCapture.Animations; internal class OpacityAnimation : BaseAnimation { diff --git a/SnapX.Core/SharpCapture/Animations/PointAnimation.cs b/SnapX.Core/SharpCapture/Animations/PointAnimation.cs index 8d8fa17e5..a400f2216 100644 --- a/SnapX.Core/SharpCapture/Animations/PointAnimation.cs +++ b/SnapX.Core/SharpCapture/Animations/PointAnimation.cs @@ -4,7 +4,7 @@ using SixLabors.ImageSharp; -namespace SnapX.Core.ScreenCapture.Animations; +namespace SnapX.Core.SharpCapture.Animations; internal class PointAnimation : BaseAnimation { diff --git a/SnapX.Core/SharpCapture/Animations/RectangleAnimation.cs b/SnapX.Core/SharpCapture/Animations/RectangleAnimation.cs index bbb847fb2..6fb510e31 100644 --- a/SnapX.Core/SharpCapture/Animations/RectangleAnimation.cs +++ b/SnapX.Core/SharpCapture/Animations/RectangleAnimation.cs @@ -5,7 +5,7 @@ using SixLabors.ImageSharp; using SnapX.Core.Utils; -namespace SnapX.Core.ScreenCapture.Animations; +namespace SnapX.Core.SharpCapture.Animations; internal class RectangleAnimation : BaseAnimation { diff --git a/SnapX.Core/SharpCapture/Animations/TextAnimation.cs b/SnapX.Core/SharpCapture/Animations/TextAnimation.cs index 0aa338fa2..924105c3c 100644 --- a/SnapX.Core/SharpCapture/Animations/TextAnimation.cs +++ b/SnapX.Core/SharpCapture/Animations/TextAnimation.cs @@ -4,7 +4,7 @@ using System.Drawing; -namespace SnapX.Core.ScreenCapture.Animations; +namespace SnapX.Core.SharpCapture.Animations; internal class TextAnimation : OpacityAnimation { diff --git a/SnapX.Core/SharpCapture/BaseCapture.cs b/SnapX.Core/SharpCapture/BaseSharpCapture.cs similarity index 72% rename from SnapX.Core/SharpCapture/BaseCapture.cs rename to SnapX.Core/SharpCapture/BaseSharpCapture.cs index 3575fe015..105046af1 100644 --- a/SnapX.Core/SharpCapture/BaseCapture.cs +++ b/SnapX.Core/SharpCapture/BaseSharpCapture.cs @@ -1,19 +1,21 @@ using SixLabors.ImageSharp; +using SnapX.Core.Job; + #pragma warning disable CS1998 namespace SnapX.Core.SharpCapture; -public abstract class BaseCapture +public abstract class BaseSharpCapture { - public virtual async Task CaptureScreen(Rectangle bounds) => + public virtual async Task CaptureScreen(Rectangle bounds, TaskSettings? taskSettings = null) => throw new NotImplementedException("SharpCapture CaptureScreen is not implemented."); - public virtual async Task CaptureScreen(Point? pos) => + public virtual async Task CaptureScreen(Point? pos, TaskSettings? taskSettings = null) => throw new NotImplementedException("SharpCapture CaptureScreen is not implemented."); - public virtual async Task CaptureWindow(Point pos) => + public virtual async Task CaptureWindow(Point pos, TaskSettings? taskSettings = null) => throw new NotImplementedException("SharpCapture CaptureWindow is not implemented."); - public virtual async Task CaptureRectangle(Rectangle rect) => + public virtual async Task CaptureRectangle(Rectangle rect, TaskSettings? taskSettings = null) => throw new NotImplementedException("SharpCapture CaptureRectangle is not implemented."); - public virtual async Task CaptureFullscreen() => + public virtual async Task CaptureFullscreen(TaskSettings? taskSettings = null) => throw new NotImplementedException("SharpCapture CaptureFullscreen is not implemented."); public virtual async Task GetWorkingArea() => throw new NotImplementedException("SharpCapture GetWorkingArea is not implemented."); diff --git a/SnapX.Core/SharpCapture/CaptureActiveMonitor.cs b/SnapX.Core/SharpCapture/CaptureActiveMonitor.cs new file mode 100644 index 000000000..fd9cab7d9 --- /dev/null +++ b/SnapX.Core/SharpCapture/CaptureActiveMonitor.cs @@ -0,0 +1,36 @@ + +// SPDX-License-Identifier: GPL-3.0-or-later + + +using SnapX.Core.Interfaces; +using SnapX.Core.Job; +using SnapX.Core.SharpCapture.Interfaces; + +namespace SnapX.Core.SharpCapture; + +public class CaptureActiveMonitor( + IMainWindowService MainWindowService, + INotificationService NotificationService, + IUploadManager UploadManager, + IDelayService DelayService, + ILoggerService _logger, + ICaptureService CaptureService) + : CaptureBase(MainWindowService, NotificationService, UploadManager, DelayService, _logger, CaptureService) +{ + protected override async Task ExecuteAsync(TaskSettings taskSettings) + { + _logger.Debug("CaptureActiveMonitor started"); + + var img = await _captureService + .CaptureActiveMonitorAsync(taskSettings) + .ConfigureAwait(false); + if (img is null) + { + _logger.Debug("CaptureActiveMonitorAsync returned null. Returning empty TaskMetadata"); + return new TaskMetadata(); + } + var metadata = CreateMetadata(img.Bounds); + metadata.Image = img; + return metadata; + } +} diff --git a/SnapX.Core/SharpCapture/CaptureActiveWindow.cs b/SnapX.Core/SharpCapture/CaptureActiveWindow.cs new file mode 100644 index 000000000..14e2590fe --- /dev/null +++ b/SnapX.Core/SharpCapture/CaptureActiveWindow.cs @@ -0,0 +1,33 @@ + +// SPDX-License-Identifier: GPL-3.0-or-later + + +using SnapX.Core.Interfaces; +using SnapX.Core.Job; +using SnapX.Core.SharpCapture.Interfaces; + +namespace SnapX.Core.SharpCapture; +public class CaptureActiveWindow( + IMainWindowService MainWindowService, + INotificationService NotificationService, + IUploadManager UploadManager, + IDelayService DelayService, + ILoggerService LoggerService, + ICaptureService CaptureService) + : CaptureBase(MainWindowService, NotificationService, UploadManager, DelayService, LoggerService, CaptureService) +{ + + protected override async Task ExecuteAsync(TaskSettings taskSettings) + { + var metadata = CreateMetadata(); + + if (taskSettings.CaptureSettings is { CaptureTransparent: true, CaptureClientArea: false }) + { + LoggerService.Debug("Capture transparent mode is default now. Non transparent mode is not implemented"); + } + + metadata.Image = await _captureService.CaptureActiveWindowAsync(); + + return metadata; + } +} diff --git a/SnapX.Core/SharpCapture/CaptureBase.cs b/SnapX.Core/SharpCapture/CaptureBase.cs new file mode 100644 index 000000000..5a4c98edb --- /dev/null +++ b/SnapX.Core/SharpCapture/CaptureBase.cs @@ -0,0 +1,146 @@ + +// SPDX-License-Identifier: GPL-3.0-or-later + + +using SixLabors.ImageSharp; +using SnapX.Core.Interfaces; +using SnapX.Core.Job; +using SnapX.Core.SharpCapture.Interfaces; +using SnapX.Core.Utils.Extensions; +using SnapX.Core.Utils.Native; + +namespace SnapX.Core.SharpCapture; +public abstract class CaptureBase( + IMainWindowService MainWindowService, + INotificationService NotificationService, + IUploadManager UploadManager, + IDelayService DelayService, + ILoggerService LoggerService, + ICaptureService CaptureService) +{ + public bool AllowAutoHideForm { get; set; } = true; + public bool AllowAnnotation { get; set; } = true; + + internal readonly ICaptureService _captureService = CaptureService; + + public async Task CaptureAsync(TaskSettings? taskSettings = null, bool autoHideForm = false) + { + using (LoggerService.BeginScope("Capture")) + { + if (taskSettings == null) + { + taskSettings = TaskSettings.GetDefaultTaskSettings(); + LoggerService.Debug("Loaded default task settings"); + } + + if (taskSettings.CaptureSettings.ScreenshotDelay > 0) + { + var delay = (int)(taskSettings.CaptureSettings.ScreenshotDelay * 1000); + LoggerService.Information("Delaying capture for {Delay} ms as configured", delay); + await DelayService.DelayAsync(delay); + } + + await CaptureInternalAsync(taskSettings, autoHideForm); + } + } + + private async Task CaptureInternalAsync(TaskSettings taskSettings, bool autoHideForm) + { + using (LoggerService.BeginScope("CaptureInternal")) + { + if (autoHideForm && AllowAutoHideForm) + { + LoggerService.Debug("Hiding main window for capture"); + await MainWindowService.HideAsync(); + await DelayService.DelayAsync(250); + } + + TaskMetadata? metadata = null; + + try + { + AllowAnnotation = true; + LoggerService.Debug("Executing capture logic in {CaptureType}", GetType().Name); + metadata = await ExecuteAsync(taskSettings); + } + catch (Exception ex) + { + LoggerService.Error(ex, "An error occurred during capture"); + } + finally + { + if (autoHideForm && AllowAutoHideForm) + { + LoggerService.Debug("Re-activating main window after capture"); + await MainWindowService.ForceActivateAsync(); + } + + await AfterCaptureAsync(metadata, taskSettings); + } + } + } + + protected virtual async Task AfterCaptureAsync(TaskMetadata? metadata, TaskSettings taskSettings) + { + using (LoggerService.BeginScope("AfterCapture")) + { + if (metadata is { Image: not null }) + { + LoggerService.Debug("Running AfterCapture tasks"); + + await NotificationService + .PlayNotificationSoundAsync(NotificationSound.Capture, taskSettings); + + if (taskSettings.AfterCaptureJob.HasFlag(AfterCaptureTasks.AnnotateImage) && !AllowAnnotation) + { + taskSettings.AfterCaptureJob = + taskSettings.AfterCaptureJob.Remove(AfterCaptureTasks.AnnotateImage); + + LoggerService.Information("Annotation disabled. Removed AnnotateImage from AfterCapture tasks"); + } + + if (taskSettings.ImageSettings.ImageEffectOnlyRegionCapture && + GetType() != typeof(CaptureRegion) && GetType() != typeof(CaptureLastRegion)) + { + taskSettings.AfterCaptureJob = + taskSettings.AfterCaptureJob.Remove(AfterCaptureTasks.AddImageEffects); + + LoggerService.Information("Skipped image effects because ImageEffectOnlyRegionCapture is true"); + } + + await UploadManager.RunImageTaskAsync(metadata, taskSettings); + LoggerService.Information("Upload service completed image processing"); + } + else + { + LoggerService.Warning("No image captured. Skipping AfterCapture tasks"); + } + } + } + + protected abstract Task ExecuteAsync(TaskSettings taskSettings); + + protected TaskMetadata CreateMetadata() + { + return CreateMetadata(Rectangle.Empty, null); + } + + protected TaskMetadata CreateMetadata(Rectangle insideRect, string? ignoreProcess = "explorer") + { + var metadata = new TaskMetadata(); + + var windowInfo = Methods.GetForegroundWindow(); + if ((ignoreProcess == null || !windowInfo.ProcessName.Equals(ignoreProcess, StringComparison.OrdinalIgnoreCase)) && + (insideRect.IsEmpty || windowInfo.Rectangle.Contains(insideRect))) + { + metadata.UpdateInfo(windowInfo); + LoggerService.Debug("Foreground window info added to capture metadata: {ProcessName}", windowInfo.ProcessName); + } + else + { + LoggerService.Debug("Window info skipped because it didn't match criteria. IgnoreProcess={IgnoreProcess}", ignoreProcess ?? string.Empty); + } + + return metadata; + } +} diff --git a/SnapX.Core/SharpCapture/CaptureCustomRegion.cs b/SnapX.Core/SharpCapture/CaptureCustomRegion.cs new file mode 100644 index 000000000..abd0aa692 --- /dev/null +++ b/SnapX.Core/SharpCapture/CaptureCustomRegion.cs @@ -0,0 +1,21 @@ + +// SPDX-License-Identifier: GPL-3.0-or-later + + +using SnapX.Core.Interfaces; +using SnapX.Core.Job; +using SnapX.Core.SharpCapture.Interfaces; + +namespace SnapX.Core.SharpCapture; + +public class CaptureCustomRegion(IMainWindowService MainWindowService, INotificationService NotificationService, IUploadManager UploadManager, IDelayService DelayService, ILoggerService LoggerService, ICaptureService CaptureService) : CaptureBase(MainWindowService, NotificationService, UploadManager, DelayService, LoggerService, CaptureService) +{ + protected override async Task ExecuteAsync(TaskSettings taskSettings) + { + var rect = taskSettings.CaptureSettings.CaptureCustomRegion; + var metadata = CreateMetadata(rect); + metadata.Image = await _captureService.CaptureRectangle(taskSettings, rect); + return metadata; + } +} + diff --git a/SnapX.Core/SharpCapture/CaptureCustomWindow.cs b/SnapX.Core/SharpCapture/CaptureCustomWindow.cs new file mode 100644 index 000000000..d25720f1b --- /dev/null +++ b/SnapX.Core/SharpCapture/CaptureCustomWindow.cs @@ -0,0 +1,35 @@ + +// SPDX-License-Identifier: GPL-3.0-or-later + + +using SnapX.Core.Interfaces; +using SnapX.Core.SharpCapture.Interfaces; + +namespace SnapX.Core.SharpCapture; +public class CaptureCustomWindow(IMainWindowService MainWindowService, INotificationService NotificationService, IUploadManager UploadManager, IDelayService DelayService, ILoggerService LoggerService, ICaptureService CaptureService, IntPtr? WindowHandle) : CaptureWindow(MainWindowService, NotificationService, UploadManager, DelayService, LoggerService, CaptureService, WindowHandle) +{ + // protected override TaskMetadata Execute(TaskSettings? taskSettings) + // { + // string windowTitle = taskSettings.CaptureSettings.CaptureCustomWindow; + // + // if (!string.IsNullOrEmpty(windowTitle)) + // { + // // TODO: Reimplement w/ Windows support & Linux (X11, and KDE Plasma Wayland) + // // IntPtr hWnd = NativeMethods.SearchWindow(windowTitle); + // // + // // if (hWnd == IntPtr.Zero) + // // { + // // MessageBox.Show(Resources.UnableToFindAWindowWithSpecifiedWindowTitle, "SnapX", MessageBoxButtons.OK, MessageBoxIcon.Information); + // // } + // // else + // // { + // // WindowHandle = hWnd; + // // + // // return base.Execute(taskSettings); + // // } + // } + // + // return null; + // } +} + diff --git a/SnapX.Core/SharpCapture/CaptureFullscreen.cs b/SnapX.Core/SharpCapture/CaptureFullscreen.cs new file mode 100644 index 000000000..b41882721 --- /dev/null +++ b/SnapX.Core/SharpCapture/CaptureFullscreen.cs @@ -0,0 +1,27 @@ + +// SPDX-License-Identifier: GPL-3.0-or-later + + +using SnapX.Core.Interfaces; +using SnapX.Core.Job; +using SnapX.Core.SharpCapture.Interfaces; + +namespace SnapX.Core.SharpCapture; + +public class CaptureFullscreen(IMainWindowService MainWindowService, INotificationService NotificationService, IUploadManager UploadManager, IDelayService DelayService, ILoggerService LoggerService, ICaptureService CaptureService) : CaptureBase(MainWindowService, NotificationService, UploadManager, DelayService, LoggerService, CaptureService) +{ + // protected override TaskMetadata Execute(TaskSettings? taskSettings) + // { + // DebugHelper.WriteLine("CaptureFullscreen"); + // var img = TaskHelpers.GetScreenshot(taskSettings).CaptureFullscreen(); + // var metadata = CreateMetadata(img.Bounds); + // metadata.Image = img; + // + // return metadata; + // } + protected override async Task ExecuteAsync(TaskSettings taskSettings) + { + throw new NotImplementedException(); + } +} + diff --git a/SnapX.Core/SharpCapture/CaptureLastRegion.cs b/SnapX.Core/SharpCapture/CaptureLastRegion.cs new file mode 100644 index 000000000..530d24806 --- /dev/null +++ b/SnapX.Core/SharpCapture/CaptureLastRegion.cs @@ -0,0 +1,27 @@ + +// SPDX-License-Identifier: GPL-3.0-or-later + + +using SnapX.Core.Interfaces; +using SnapX.Core.Job; +using SnapX.Core.SharpCapture.Interfaces; + +namespace SnapX.Core.SharpCapture; +public class CaptureLastRegion(IMainWindowService MainWindowService, INotificationService NotificationService, IUploadManager UploadManager, IDelayService DelayService, ILoggerService LoggerService, ICaptureService CaptureService, RegionCaptureType RegionCaptureType) : CaptureRegion(MainWindowService, NotificationService, UploadManager, DelayService, LoggerService, CaptureService, RegionCaptureType) +{ + protected override async Task ExecuteAsync(TaskSettings taskSettings) + { + throw new NotImplementedException(); + } + // protected override TaskMetadata Execute(TaskSettings taskSettings) + // { + // switch (lastRegionCaptureType) + // { + // default: + // case RegionCaptureType.Default: return ExecuteRegionCapture(taskSettings); + // case RegionCaptureType.Light: return ExecuteRegionCaptureLight(taskSettings); + // case RegionCaptureType.Transparent: return ExecuteRegionCaptureTransparent(taskSettings); + // } + // } +} + diff --git a/SnapX.Core/SharpCapture/CaptureMonitor.cs b/SnapX.Core/SharpCapture/CaptureMonitor.cs new file mode 100644 index 000000000..e3aa69da5 --- /dev/null +++ b/SnapX.Core/SharpCapture/CaptureMonitor.cs @@ -0,0 +1,28 @@ + +// SPDX-License-Identifier: GPL-3.0-or-later + + +using SixLabors.ImageSharp; +using SnapX.Core.Interfaces; +using SnapX.Core.Job; +using SnapX.Core.SharpCapture.Interfaces; + +namespace SnapX.Core.SharpCapture; +public class CaptureMonitor(IMainWindowService MainWindowService, INotificationService NotificationService, IUploadManager UploadManager, IDelayService DelayService, ILoggerService LoggerService, ICaptureService CaptureService, Rectangle MonitorRectangle) : CaptureBase(MainWindowService, NotificationService, UploadManager, DelayService, LoggerService, CaptureService) +{ + public Rectangle MonitorRectangle { get; private set; } = MonitorRectangle; + + + // protected override TaskMetadata Execute(TaskSettings taskSettings) + // { + // DebugHelper.WriteLine("CaptureMonitor Start"); + // var metadata = CreateMetadata(MonitorRectangle); + // metadata.Image = TaskHelpers.GetScreenshot().CaptureRectangle(MonitorRectangle); + // return metadata; + // } + protected override async Task ExecuteAsync(TaskSettings taskSettings) + { + throw new NotImplementedException(); + } +} + diff --git a/SnapX.Core/Capture/CaptureRegion.cs b/SnapX.Core/SharpCapture/CaptureRegion.cs similarity index 77% rename from SnapX.Core/Capture/CaptureRegion.cs rename to SnapX.Core/SharpCapture/CaptureRegion.cs index 8828e97c7..02920c3c3 100644 --- a/SnapX.Core/Capture/CaptureRegion.cs +++ b/SnapX.Core/SharpCapture/CaptureRegion.cs @@ -2,37 +2,30 @@ // SPDX-License-Identifier: GPL-3.0-or-later +using SnapX.Core.Interfaces; using SnapX.Core.Job; +using SnapX.Core.SharpCapture.Interfaces; -namespace SnapX.Core.Capture; -public class CaptureRegion : CaptureBase +namespace SnapX.Core.SharpCapture; +public class CaptureRegion(IMainWindowService MainWindowService, INotificationService NotificationService, IUploadManager UploadManager, IDelayService DelayService, ILoggerService LoggerService, ICaptureService CaptureService, RegionCaptureType RegionCaptureType) : CaptureBase(MainWindowService, NotificationService, UploadManager, DelayService, LoggerService, CaptureService) { protected static RegionCaptureType lastRegionCaptureType = RegionCaptureType.Default; - public RegionCaptureType RegionCaptureType { get; protected set; } + public RegionCaptureType RegionCaptureType { get; protected set; } = RegionCaptureType; - public CaptureRegion() - { - } - - public CaptureRegion(RegionCaptureType regionCaptureType) - { - RegionCaptureType = regionCaptureType; - } - - protected override TaskMetadata Execute(TaskSettings taskSettings) - { - switch (RegionCaptureType) - { - default: - case RegionCaptureType.Default: - return ExecuteRegionCapture(taskSettings); - case RegionCaptureType.Light: - return ExecuteRegionCaptureLight(taskSettings); - case RegionCaptureType.Transparent: - return ExecuteRegionCaptureTransparent(taskSettings); - } - } + // protected override TaskMetadata Execute(TaskSettings taskSettings) + // { + // switch (RegionCaptureType) + // { + // default: + // case RegionCaptureType.Default: + // return ExecuteRegionCapture(taskSettings); + // case RegionCaptureType.Light: + // return ExecuteRegionCaptureLight(taskSettings); + // case RegionCaptureType.Transparent: + // return ExecuteRegionCaptureTransparent(taskSettings); + // } + // } protected TaskMetadata ExecuteRegionCapture(TaskSettings taskSettings) { @@ -140,5 +133,10 @@ protected TaskMetadata ExecuteRegionCaptureTransparent(TaskSettings taskSettings return null; } + + protected override async Task ExecuteAsync(TaskSettings taskSettings) + { + throw new NotImplementedException(); + } } diff --git a/SnapX.Core/SharpCapture/CaptureWindow.cs b/SnapX.Core/SharpCapture/CaptureWindow.cs new file mode 100644 index 000000000..78ff2becb --- /dev/null +++ b/SnapX.Core/SharpCapture/CaptureWindow.cs @@ -0,0 +1,49 @@ + +// SPDX-License-Identifier: GPL-3.0-or-later + + +using SnapX.Core.Interfaces; +using SnapX.Core.Job; +using SnapX.Core.SharpCapture.Interfaces; + +namespace SnapX.Core.SharpCapture; +public class CaptureWindow(IMainWindowService MainWindowService, INotificationService NotificationService, IUploadManager UploadManager, IDelayService DelayService, ILoggerService LoggerService, ICaptureService CaptureService, IntPtr? WindowHandle = 0) : CaptureBase(MainWindowService, NotificationService, UploadManager, DelayService, LoggerService, CaptureService) +{ + public IntPtr WindowHandle { get; protected set; } = WindowHandle.GetValueOrDefault(IntPtr.Zero); + + // protected override TaskMetadata Execute(TaskSettings? taskSettings) + // { + // WindowInfo windowInfo = new(WindowHandle); + // + // if (windowInfo.IsMinimized) + // { + // windowInfo.Restore(); + // Thread.Sleep(250); + // } + // + // if (!windowInfo.IsActive) + // { + // windowInfo.Activate(); + // Thread.Sleep(100); + // } + // + // var metadata = new TaskMetadata(); + // metadata.UpdateInfo(windowInfo); + // + // if (taskSettings.CaptureSettings.CaptureTransparent && !taskSettings.CaptureSettings.CaptureClientArea) + // { + // metadata.Image = TaskHelpers.GetScreenshot(taskSettings).CaptureWindowTransparent(WindowHandle); + // } + // else + // { + // metadata.Image = TaskHelpers.GetScreenshot(taskSettings).CaptureWindow(WindowHandle); + // } + // + // return metadata; + // } + protected override async Task ExecuteAsync(TaskSettings taskSettings) + { + throw new NotImplementedException(); + } +} + diff --git a/SnapX.Core/ScreenCapture/Enums.cs b/SnapX.Core/SharpCapture/Enums.cs similarity index 99% rename from SnapX.Core/ScreenCapture/Enums.cs rename to SnapX.Core/SharpCapture/Enums.cs index 4ea2ad274..39ba38537 100644 --- a/SnapX.Core/ScreenCapture/Enums.cs +++ b/SnapX.Core/SharpCapture/Enums.cs @@ -4,7 +4,7 @@ using System.ComponentModel; -namespace SnapX.Core.ScreenCapture; +namespace SnapX.Core.SharpCapture; public enum ScreenRecordOutput { diff --git a/SnapX.Core/SharpCapture/Helpers/InputManager.cs b/SnapX.Core/SharpCapture/Helpers/InputManager.cs index 4d6bb8917..24628b06d 100644 --- a/SnapX.Core/SharpCapture/Helpers/InputManager.cs +++ b/SnapX.Core/SharpCapture/Helpers/InputManager.cs @@ -4,7 +4,7 @@ using SixLabors.ImageSharp; -namespace SnapX.Core.ScreenCapture.Helpers; +namespace SnapX.Core.SharpCapture.Helpers; public class InputManager { diff --git a/SnapX.Core/SharpCapture/Helpers/LocationInfo.cs b/SnapX.Core/SharpCapture/Helpers/LocationInfo.cs index 89a19a93b..cb18921bd 100644 --- a/SnapX.Core/SharpCapture/Helpers/LocationInfo.cs +++ b/SnapX.Core/SharpCapture/Helpers/LocationInfo.cs @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later -namespace SnapX.Core.ScreenCapture.Helpers; +namespace SnapX.Core.SharpCapture.Helpers; public class LocationInfo diff --git a/SnapX.Core/SharpCapture/Helpers/SimpleWindowInfo.cs b/SnapX.Core/SharpCapture/Helpers/SimpleWindowInfo.cs index 2a3ef5ec5..3993de98a 100644 --- a/SnapX.Core/SharpCapture/Helpers/SimpleWindowInfo.cs +++ b/SnapX.Core/SharpCapture/Helpers/SimpleWindowInfo.cs @@ -5,7 +5,7 @@ using SixLabors.ImageSharp; using SnapX.Core.Media; -namespace SnapX.Core.ScreenCapture.Helpers; +namespace SnapX.Core.SharpCapture.Helpers; public class SimpleWindowInfo diff --git a/SnapX.Core/SharpCapture/Helpers/SnapSize.cs b/SnapX.Core/SharpCapture/Helpers/SnapSize.cs index d7de82598..947d685ee 100644 --- a/SnapX.Core/SharpCapture/Helpers/SnapSize.cs +++ b/SnapX.Core/SharpCapture/Helpers/SnapSize.cs @@ -4,7 +4,7 @@ using System.Drawing; -namespace SnapX.Core.ScreenCapture.Helpers; +namespace SnapX.Core.SharpCapture.Helpers; public class SnapSize { diff --git a/SnapX.Core/SharpCapture/Helpers/WindowsList.cs b/SnapX.Core/SharpCapture/Helpers/WindowsList.cs index 1f3c37b87..31e8eaf2c 100644 --- a/SnapX.Core/SharpCapture/Helpers/WindowsList.cs +++ b/SnapX.Core/SharpCapture/Helpers/WindowsList.cs @@ -4,7 +4,7 @@ using SnapX.Core.Utils.Extensions; using SnapX.Core.Utils.Native; -namespace SnapX.Core.ScreenCapture.Helpers; +namespace SnapX.Core.SharpCapture.Helpers; public class WindowsList { diff --git a/SnapX.Core/SharpCapture/Interfaces/ICaptureService.cs b/SnapX.Core/SharpCapture/Interfaces/ICaptureService.cs new file mode 100644 index 000000000..f32c6d0bb --- /dev/null +++ b/SnapX.Core/SharpCapture/Interfaces/ICaptureService.cs @@ -0,0 +1,12 @@ +using SixLabors.ImageSharp; +using SnapX.Core.Job; + +namespace SnapX.Core.SharpCapture.Interfaces; + +public interface ICaptureService +{ + Task CaptureActiveMonitorAsync(TaskSettings? taskSettings = null); + Task CaptureFullscreenAsync(TaskSettings? taskSettings = null); + Task CaptureRectangle(TaskSettings? taskSettings = null, Rectangle? rect = null); + Task CaptureActiveWindowAsync(TaskSettings? taskSettings = null); +} diff --git a/SnapX.Core/SharpCapture/Linux/DBus/DesktopDBus.cs b/SnapX.Core/SharpCapture/Linux/DBus/DesktopDBus.cs index 62a78f26c..5a0e40ee5 100644 --- a/SnapX.Core/SharpCapture/Linux/DBus/DesktopDBus.cs +++ b/SnapX.Core/SharpCapture/Linux/DBus/DesktopDBus.cs @@ -5,127 +5,6 @@ namespace SnapX.Core.SharpCapture.Linux.DBus; -record InhibitProperties -{ - public uint Version { get; set; } = default!; -} -partial class Inhibit : DesktopObject -{ - private const string __Interface = "org.freedesktop.portal.Inhibit"; - public Inhibit(DesktopService service, ObjectPath path) : base(service, path) - { } - public Task InhibitAsync(string window, uint flags, Dictionary options) - { - return this.Connection.CallMethodAsync(CreateMessage(), (Message m, object? s) => ReadMessage_o(m, (DesktopObject)s!), this); - MessageBuffer CreateMessage() - { - var writer = this.Connection.GetMessageWriter(); - writer.WriteMethodCallHeader( - destination: Service.Destination, - path: Path, - @interface: __Interface, - signature: "sua{sv}", - member: "Inhibit"); - writer.WriteString(window); - writer.WriteUInt32(flags); - writer.WriteDictionary(options); - return writer.CreateMessage(); - } - } - public Task CreateMonitorAsync(string window, Dictionary options) - { - return this.Connection.CallMethodAsync(CreateMessage(), (Message m, object? s) => ReadMessage_o(m, (DesktopObject)s!), this); - MessageBuffer CreateMessage() - { - var writer = this.Connection.GetMessageWriter(); - writer.WriteMethodCallHeader( - destination: Service.Destination, - path: Path, - @interface: __Interface, - signature: "sa{sv}", - member: "CreateMonitor"); - writer.WriteString(window); - writer.WriteDictionary(options); - return writer.CreateMessage(); - } - } - public Task QueryEndResponseAsync(ObjectPath sessionHandle) - { - return this.Connection.CallMethodAsync(CreateMessage()); - MessageBuffer CreateMessage() - { - var writer = this.Connection.GetMessageWriter(); - writer.WriteMethodCallHeader( - destination: Service.Destination, - path: Path, - @interface: __Interface, - signature: "o", - member: "QueryEndResponse"); - writer.WriteObjectPath(sessionHandle); - return writer.CreateMessage(); - } - } - public ValueTask WatchStateChangedAsync(Action State)> handler, bool emitOnCapturedContext = true, ObserverFlags flags = ObserverFlags.None) - => base.WatchSignalAsync(Service.Destination, __Interface, Path, "StateChanged", (Message m, object? s) => ReadMessage_oaesv(m, (DesktopObject)s!), handler, emitOnCapturedContext, flags); - public Task GetVersionAsync() - => this.Connection.CallMethodAsync(CreateGetPropertyMessage(__Interface, "version"), (Message m, object? s) => ReadMessage_v_u(m, (DesktopObject)s!), this); - public Task GetPropertiesAsync() - { - return this.Connection.CallMethodAsync(CreateGetAllPropertiesMessage(__Interface), (Message m, object? s) => ReadMessage(m, (DesktopObject)s!), this); - static InhibitProperties ReadMessage(Message message, DesktopObject _) - { - var reader = message.GetBodyReader(); - return ReadProperties(ref reader); - } - } - public ValueTask WatchPropertiesChangedAsync(Action> handler, bool emitOnCapturedContext = true, ObserverFlags flags = ObserverFlags.None) - { - return base.WatchPropertiesChangedAsync(__Interface, (Message m, object? s) => ReadMessage(m, (DesktopObject)s!), handler, emitOnCapturedContext, flags); - static PropertyChanges ReadMessage(Message message, DesktopObject _) - { - var reader = message.GetBodyReader(); - reader.ReadString(); // interface - List changed = new(), invalidated = new(); - return new PropertyChanges(ReadProperties(ref reader, changed), ReadInvalidated(ref reader), changed.ToArray()); - } - static string[] ReadInvalidated(ref Reader reader) - { - List? invalidated = null; - ArrayEnd arrayEnd = reader.ReadArrayStart(DBusType.String); - while (reader.HasNext(arrayEnd)) - { - invalidated ??= new(); - var property = reader.ReadString(); - switch (property) - { - case "version": invalidated.Add("Version"); break; - } - } - return invalidated?.ToArray() ?? Array.Empty(); - } - } - private static InhibitProperties ReadProperties(ref Reader reader, List? changedList = null) - { - var props = new InhibitProperties(); - ArrayEnd arrayEnd = reader.ReadArrayStart(DBusType.Struct); - while (reader.HasNext(arrayEnd)) - { - var property = reader.ReadString(); - switch (property) - { - case "version": - reader.ReadSignature("u"u8); - props.Version = reader.ReadUInt32(); - changedList?.Add("Version"); - break; - default: - reader.ReadVariantValue(); - break; - } - } - return props; - } -} record BackgroundProperties { public uint Version { get; set; } = default!; @@ -227,110 +106,6 @@ private static BackgroundProperties ReadProperties(ref Reader reader, List CreateSessionAsync(Dictionary options) - { - return this.Connection.CallMethodAsync(CreateMessage(), (Message m, object? s) => ReadMessage_o(m, (DesktopObject)s!), this); - MessageBuffer CreateMessage() - { - var writer = this.Connection.GetMessageWriter(); - writer.WriteMethodCallHeader( - destination: Service.Destination, - path: Path, - @interface: __Interface, - signature: "a{sv}", - member: "CreateSession"); - writer.WriteDictionary(options); - return writer.CreateMessage(); - } - } - public Task StartAsync(ObjectPath sessionHandle, string parentWindow, Dictionary options) - { - return this.Connection.CallMethodAsync(CreateMessage(), (Message m, object? s) => ReadMessage_o(m, (DesktopObject)s!), this); - MessageBuffer CreateMessage() - { - var writer = this.Connection.GetMessageWriter(); - writer.WriteMethodCallHeader( - destination: Service.Destination, - path: Path, - @interface: __Interface, - signature: "osa{sv}", - member: "Start"); - writer.WriteObjectPath(sessionHandle); - writer.WriteString(parentWindow); - writer.WriteDictionary(options); - return writer.CreateMessage(); - } - } - public ValueTask WatchLocationUpdatedAsync(Action Location)> handler, bool emitOnCapturedContext = true, ObserverFlags flags = ObserverFlags.None) - => base.WatchSignalAsync(Service.Destination, __Interface, Path, "LocationUpdated", (Message m, object? s) => ReadMessage_oaesv(m, (DesktopObject)s!), handler, emitOnCapturedContext, flags); - public Task GetVersionAsync() - => this.Connection.CallMethodAsync(CreateGetPropertyMessage(__Interface, "version"), (Message m, object? s) => ReadMessage_v_u(m, (DesktopObject)s!), this); - public Task GetPropertiesAsync() - { - return this.Connection.CallMethodAsync(CreateGetAllPropertiesMessage(__Interface), (Message m, object? s) => ReadMessage(m, (DesktopObject)s!), this); - static LocationProperties ReadMessage(Message message, DesktopObject _) - { - var reader = message.GetBodyReader(); - return ReadProperties(ref reader); - } - } - public ValueTask WatchPropertiesChangedAsync(Action> handler, bool emitOnCapturedContext = true, ObserverFlags flags = ObserverFlags.None) - { - return base.WatchPropertiesChangedAsync(__Interface, (Message m, object? s) => ReadMessage(m, (DesktopObject)s!), handler, emitOnCapturedContext, flags); - static PropertyChanges ReadMessage(Message message, DesktopObject _) - { - var reader = message.GetBodyReader(); - reader.ReadString(); // interface - List changed = new(), invalidated = new(); - return new PropertyChanges(ReadProperties(ref reader, changed), ReadInvalidated(ref reader), changed.ToArray()); - } - static string[] ReadInvalidated(ref Reader reader) - { - List? invalidated = null; - ArrayEnd arrayEnd = reader.ReadArrayStart(DBusType.String); - while (reader.HasNext(arrayEnd)) - { - invalidated ??= new(); - var property = reader.ReadString(); - switch (property) - { - case "version": invalidated.Add("Version"); break; - } - } - return invalidated?.ToArray() ?? Array.Empty(); - } - } - private static LocationProperties ReadProperties(ref Reader reader, List? changedList = null) - { - var props = new LocationProperties(); - ArrayEnd arrayEnd = reader.ReadArrayStart(DBusType.Struct); - while (reader.HasNext(arrayEnd)) - { - var property = reader.ReadString(); - switch (property) - { - case "version": - reader.ReadSignature("u"u8); - props.Version = reader.ReadUInt32(); - changedList?.Add("Version"); - break; - default: - reader.ReadVariantValue(); - break; - } - } - return props; - } -} record NotificationProperties { public Dictionary SupportedOptions { get; set; } = default!; @@ -2862,91 +2637,6 @@ private static ScreenCastProperties ReadProperties(ref Reader reader, List ComposeEmailAsync(string parentWindow, Dictionary options) - { - return this.Connection.CallMethodAsync(CreateMessage(), (Message m, object? s) => ReadMessage_o(m, (DesktopObject)s!), this); - MessageBuffer CreateMessage() - { - var writer = this.Connection.GetMessageWriter(); - writer.WriteMethodCallHeader( - destination: Service.Destination, - path: Path, - @interface: __Interface, - signature: "sa{sv}", - member: "ComposeEmail"); - writer.WriteString(parentWindow); - writer.WriteDictionary(options); - return writer.CreateMessage(); - } - } - public Task GetVersionAsync() - => this.Connection.CallMethodAsync(CreateGetPropertyMessage(__Interface, "version"), (Message m, object? s) => ReadMessage_v_u(m, (DesktopObject)s!), this); - public Task GetPropertiesAsync() - { - return this.Connection.CallMethodAsync(CreateGetAllPropertiesMessage(__Interface), (Message m, object? s) => ReadMessage(m, (DesktopObject)s!), this); - static EmailProperties ReadMessage(Message message, DesktopObject _) - { - var reader = message.GetBodyReader(); - return ReadProperties(ref reader); - } - } - public ValueTask WatchPropertiesChangedAsync(Action> handler, bool emitOnCapturedContext = true, ObserverFlags flags = ObserverFlags.None) - { - return base.WatchPropertiesChangedAsync(__Interface, (Message m, object? s) => ReadMessage(m, (DesktopObject)s!), handler, emitOnCapturedContext, flags); - static PropertyChanges ReadMessage(Message message, DesktopObject _) - { - var reader = message.GetBodyReader(); - reader.ReadString(); // interface - List changed = new(), invalidated = new(); - return new PropertyChanges(ReadProperties(ref reader, changed), ReadInvalidated(ref reader), changed.ToArray()); - } - static string[] ReadInvalidated(ref Reader reader) - { - List? invalidated = null; - ArrayEnd arrayEnd = reader.ReadArrayStart(DBusType.String); - while (reader.HasNext(arrayEnd)) - { - invalidated ??= new(); - var property = reader.ReadString(); - switch (property) - { - case "version": invalidated.Add("Version"); break; - } - } - return invalidated?.ToArray() ?? Array.Empty(); - } - } - private static EmailProperties ReadProperties(ref Reader reader, List? changedList = null) - { - var props = new EmailProperties(); - ArrayEnd arrayEnd = reader.ReadArrayStart(DBusType.Struct); - while (reader.HasNext(arrayEnd)) - { - var property = reader.ReadString(); - switch (property) - { - case "version": - reader.ReadSignature("u"u8); - props.Version = reader.ReadUInt32(); - changedList?.Add("Version"); - break; - default: - reader.ReadVariantValue(); - break; - } - } - return props; - } -} record TrashProperties { public uint Version { get; set; } = default!; @@ -3327,30 +3017,14 @@ partial class DesktopService public string Destination { get; } public DesktopService(Tmds.DBus.Protocol.Connection connection, string destination) => (Connection, Destination) = (connection, destination); - public Inhibit CreateInhibit(ObjectPath path) => new Inhibit(this, path); - public Background CreateBackground(ObjectPath path) => new Background(this, path); - public Location CreateLocation(ObjectPath path) => new Location(this, path); public Notification CreateNotification(ObjectPath path) => new Notification(this, path); public Screenshot CreateScreenshot(ObjectPath path) => new Screenshot(this, path); - public Account CreateAccount(ObjectPath path) => new Account(this, path); - public NetworkMonitor CreateNetworkMonitor(ObjectPath path) => new NetworkMonitor(this, path); - public Print CreatePrint(ObjectPath path) => new Print(this, path); - public Settings CreateSettings(ObjectPath path) => new Settings(this, path); - public GameMode CreateGameMode(ObjectPath path) => new GameMode(this, path); - public RemoteDesktop CreateRemoteDesktop(ObjectPath path) => new RemoteDesktop(this, path); - public MemoryMonitor CreateMemoryMonitor(ObjectPath path) => new MemoryMonitor(this, path); public OpenURI CreateOpenURI(ObjectPath path) => new OpenURI(this, path); public Realtime CreateRealtime(ObjectPath path) => new Realtime(this, path); public Secret CreateSecret(ObjectPath path) => new Secret(this, path); - public Camera CreateCamera(ObjectPath path) => new Camera(this, path); public InputCapture CreateInputCapture(ObjectPath path) => new InputCapture(this, path); public GlobalShortcuts CreateGlobalShortcuts(ObjectPath path) => new GlobalShortcuts(this, path); - public PowerProfileMonitor CreatePowerProfileMonitor(ObjectPath path) => new PowerProfileMonitor(this, path); - public DynamicLauncher CreateDynamicLauncher(ObjectPath path) => new DynamicLauncher(this, path); public ScreenCast CreateScreenCast(ObjectPath path) => new ScreenCast(this, path); - public Email CreateEmail(ObjectPath path) => new Email(this, path); - public Trash CreateTrash(ObjectPath path) => new Trash(this, path); - public ProxyResolver CreateProxyResolver(ObjectPath path) => new ProxyResolver(this, path); public FileChooser CreateFileChooser(ObjectPath path) => new FileChooser(this, path); public Session CreateSession(ObjectPath path) => new Session(this, path); } diff --git a/SnapX.Core/SharpCapture/Linux/DBus/PropertyChanges.cs b/SnapX.Core/SharpCapture/Linux/DBus/PropertyChanges.cs index ed73bd2d4..6fe1861be 100644 --- a/SnapX.Core/SharpCapture/Linux/DBus/PropertyChanges.cs +++ b/SnapX.Core/SharpCapture/Linux/DBus/PropertyChanges.cs @@ -1,12 +1,10 @@ namespace SnapX.Core.SharpCapture.Linux.DBus; -public class PropertyChanges +public class PropertyChanges(TProperties Properties, string[] Invalidated, string[] Changed) { - public PropertyChanges(TProperties properties, string[] invalidated, string[] changed) - => (Properties, Invalidated, Changed) = (properties, invalidated, changed); - public TProperties Properties { get; } - public string[] Invalidated { get; } - public string[] Changed { get; } + public TProperties Properties { get; } = Properties; + public string[] Invalidated { get; } = Invalidated; + public string[] Changed { get; } = Changed; public bool HasChanged(string property) => Array.IndexOf(Changed, property) != -1; public bool IsInvalidated(string property) => Array.IndexOf(Invalidated, property) != -1; } diff --git a/SnapX.Core/SharpCapture/Linux/LinuxCapture.cs b/SnapX.Core/SharpCapture/Linux/LinuxCapture.cs index c9ec1da04..65fe2915c 100644 --- a/SnapX.Core/SharpCapture/Linux/LinuxCapture.cs +++ b/SnapX.Core/SharpCapture/Linux/LinuxCapture.cs @@ -1,5 +1,6 @@ using SixLabors.ImageSharp; using SixLabors.ImageSharp.Processing; +using SnapX.Core.Job; using SnapX.Core.SharpCapture.Linux.DBus; using SnapX.Core.Utils.Native; using Tmds.DBus; @@ -7,15 +8,15 @@ namespace SnapX.Core.SharpCapture.Linux; -public class LinuxCapture : BaseCapture +public class LinuxCapture : BaseSharpCapture { - public override async Task CaptureFullscreen() + public override async Task CaptureFullscreen(TaskSettings? taskSettings = null) { if (LinuxAPI.IsWayland() && !IsCompositorKwin) return await TakeScreenshotWithPortal(); var screen = Methods.GetScreen(Methods.GetCursorPosition()); if (!IsCompositorKwin) { - return LinuxAPI.TakeScreenshotWithX11(screen); + return ((LinuxAPI)Methods.NativeAPI).TakeScreenshotWithX11(screen); } // Todo: replace try catch with method that checks for valid kwin permissions. @@ -122,7 +123,7 @@ private static Image CropFullscreenScreenshotToBounds(Rectangle bounds, Image im return img; } - public override async Task CaptureScreen(Rectangle bounds) + public override async Task CaptureScreen(Rectangle bounds, TaskSettings? taskSettings = null) { var fullscreenImage = await CaptureFullscreen().ConfigureAwait(false); var croppedImage = CropFullscreenScreenshotToBounds(bounds, fullscreenImage); @@ -132,7 +133,7 @@ private static Image CropFullscreenScreenshotToBounds(Rectangle bounds, Image im // return LinuxAPI.TakeScreenshotWithX11(screen); } - public override async Task CaptureScreen(Point? pos) + public override async Task CaptureScreen(Point? pos, TaskSettings? taskSettings = null) { if (pos == null || !pos.HasValue) throw new ArgumentNullException(nameof(pos)); return await CaptureScreen(await GetScreen(pos.Value)); @@ -141,7 +142,7 @@ private static Image CropFullscreenScreenshotToBounds(Rectangle bounds, Image im public override async Task GetScreen(Point pos) => Methods.NativeAPI.GetScreen(pos).Bounds; public override async Task GetWorkingArea() => ((LinuxAPI)Methods.NativeAPI).GetScreenBounds(); - public override async Task CaptureRectangle(Rectangle rect) + public override async Task CaptureRectangle(Rectangle rect, TaskSettings? taskSettings = null) { return CropFullscreenScreenshotToBounds(rect, await CaptureFullscreen().ConfigureAwait(false)); } diff --git a/SnapX.Core/ScreenCapture/RegionCaptureTasks.cs b/SnapX.Core/SharpCapture/RegionCaptureTasks.cs similarity index 98% rename from SnapX.Core/ScreenCapture/RegionCaptureTasks.cs rename to SnapX.Core/SharpCapture/RegionCaptureTasks.cs index 7d454c48d..0569accd5 100644 --- a/SnapX.Core/ScreenCapture/RegionCaptureTasks.cs +++ b/SnapX.Core/SharpCapture/RegionCaptureTasks.cs @@ -4,9 +4,9 @@ using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; using SnapX.Core.Media; -using SnapX.Core.ScreenCapture.Helpers; +using SnapX.Core.SharpCapture.Helpers; -namespace SnapX.Core.ScreenCapture; +namespace SnapX.Core.SharpCapture; public static class RegionCaptureTasks { diff --git a/SnapX.Core/SharpCapture/ScreenRecording/FFmpegCaptureDevice.cs b/SnapX.Core/SharpCapture/ScreenRecording/FFmpegCaptureDevice.cs index 46d2cf1a3..c1f14191a 100644 --- a/SnapX.Core/SharpCapture/ScreenRecording/FFmpegCaptureDevice.cs +++ b/SnapX.Core/SharpCapture/ScreenRecording/FFmpegCaptureDevice.cs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later -namespace SnapX.Core.ScreenCapture.ScreenRecording; +namespace SnapX.Core.SharpCapture.ScreenRecording; public class FFmpegCaptureDevice { diff --git a/SnapX.Core/SharpCapture/ScreenRecording/FFmpegOptions.cs b/SnapX.Core/SharpCapture/ScreenRecording/FFmpegOptions.cs index 81c821ce8..c64487e1c 100644 --- a/SnapX.Core/SharpCapture/ScreenRecording/FFmpegOptions.cs +++ b/SnapX.Core/SharpCapture/ScreenRecording/FFmpegOptions.cs @@ -2,7 +2,7 @@ using SnapX.Core.Utils; -namespace SnapX.Core.ScreenCapture.ScreenRecording; +namespace SnapX.Core.SharpCapture.ScreenRecording; public class FFmpegOptions { diff --git a/SnapX.Core/SharpCapture/ScreenRecording/HardDiskCache.cs b/SnapX.Core/SharpCapture/ScreenRecording/HardDiskCache.cs index 08d68375e..cbd0e8602 100644 --- a/SnapX.Core/SharpCapture/ScreenRecording/HardDiskCache.cs +++ b/SnapX.Core/SharpCapture/ScreenRecording/HardDiskCache.cs @@ -1,11 +1,11 @@ // SPDX-License-Identifier: GPL-3.0-or-later using SixLabors.ImageSharp; -using SnapX.Core.ScreenCapture.Helpers; +using SnapX.Core.SharpCapture.Helpers; using SnapX.Core.Utils; using SnapX.Core.Utils.Extensions; -namespace SnapX.Core.ScreenCapture.ScreenRecording; +namespace SnapX.Core.SharpCapture.ScreenRecording; public class HardDiskCache : ImageCache { diff --git a/SnapX.Core/SharpCapture/ScreenRecording/ImageCache.cs b/SnapX.Core/SharpCapture/ScreenRecording/ImageCache.cs index e583734c7..22292ced5 100644 --- a/SnapX.Core/SharpCapture/ScreenRecording/ImageCache.cs +++ b/SnapX.Core/SharpCapture/ScreenRecording/ImageCache.cs @@ -5,7 +5,7 @@ using System.Collections.Concurrent; using SixLabors.ImageSharp; -namespace SnapX.Core.ScreenCapture.ScreenRecording; +namespace SnapX.Core.SharpCapture.ScreenRecording; public abstract class ImageCache : IDisposable { diff --git a/SnapX.Core/SharpCapture/ScreenRecording/ScreenRecorder.cs b/SnapX.Core/SharpCapture/ScreenRecording/ScreenRecorder.cs index b28195deb..94f0b6c06 100644 --- a/SnapX.Core/SharpCapture/ScreenRecording/ScreenRecorder.cs +++ b/SnapX.Core/SharpCapture/ScreenRecording/ScreenRecorder.cs @@ -8,7 +8,7 @@ using SnapX.Core.Media; using SnapX.Core.Utils; -namespace SnapX.Core.ScreenCapture.ScreenRecording; +namespace SnapX.Core.SharpCapture.ScreenRecording; public class ScreenRecorder : IDisposable { diff --git a/SnapX.Core/SharpCapture/Services/CaptureService.cs b/SnapX.Core/SharpCapture/Services/CaptureService.cs new file mode 100644 index 000000000..98f63a95a --- /dev/null +++ b/SnapX.Core/SharpCapture/Services/CaptureService.cs @@ -0,0 +1,32 @@ +using SixLabors.ImageSharp; +using SnapX.Core.Job; +using SnapX.Core.SharpCapture.Interfaces; +using SnapX.Core.Utils.Native; + +namespace SnapX.Core.SharpCapture.Services; + +public class CaptureService(BaseSharpCapture _baseCapture, INativeAPI _nativeAPI) : ICaptureService +{ + public async Task CaptureActiveMonitorAsync(TaskSettings? taskSettings = null) + { + taskSettings ??= TaskSettings.GetDefaultTaskSettings(); + var bounds = await _baseCapture.GetScreen(_nativeAPI.GetCursorPosition()); + + return await _baseCapture.CaptureScreen(bounds, taskSettings); + } + + public async Task CaptureFullscreenAsync(TaskSettings? taskSettings = null) + { + throw new NotImplementedException(); + } + + public async Task CaptureRectangle(TaskSettings? taskSettings = null, Rectangle? rect = null) + { + throw new NotImplementedException(); + } + + public async Task CaptureActiveWindowAsync(TaskSettings? taskSettings = null) + { + throw new NotImplementedException(); + } +} diff --git a/SnapX.Core/SharpCapture/macOS/macOSCapture.cs b/SnapX.Core/SharpCapture/macOS/macOSCapture.cs index e05f48e50..0b3a31dd6 100644 --- a/SnapX.Core/SharpCapture/macOS/macOSCapture.cs +++ b/SnapX.Core/SharpCapture/macOS/macOSCapture.cs @@ -1,4 +1,5 @@ using SixLabors.ImageSharp; +using SnapX.Core.Job; using SnapX.Core.Utils; using SnapX.Core.Utils.Native; using uniffi.snapxrust; @@ -319,29 +320,29 @@ namespace SnapX.Core.SharpCapture.macOS; // } // } -public class macOSCapture : BaseCapture +public class macOSCapture : BaseSharpCapture { - public override async Task CaptureFullscreen() + public override async Task CaptureFullscreen(TaskSettings? taskSettings = null) { return ImageHelpers.ImageDataToImage(SnapxrustMethods.CaptureFullscreen()); } - public override async Task CaptureScreen(Rectangle bounds) + public override async Task CaptureScreen(Rectangle bounds, TaskSettings? taskSettings = null) { return CaptureRectangleNative(bounds); } - public override async Task CaptureScreen(Point? pos) + public override async Task CaptureScreen(Point? pos, TaskSettings? taskSettings = null) { return CaptureMonitor(Methods.GetCursorPosition()); } - public override async Task CaptureRectangle(Rectangle rect) + public override async Task CaptureRectangle(Rectangle rect, TaskSettings? taskSettings = null) { return CaptureRectangleNative(rect); } - public override async Task CaptureWindow(Point pos) + public override async Task CaptureWindow(Point pos, TaskSettings? taskSettings = null) { return ImageHelpers.ImageDataToImage(SnapxrustMethods.CaptureWindow((uint)pos.X, (uint)pos.Y)); } From f9e1d67f9d7f41f8ffea73a648287e1da6719700 Mon Sep 17 00:00:00 2001 From: Brycen G Date: Fri, 11 Jul 2025 19:56:58 -0400 Subject: [PATCH 10/31] chore: allow tests to access internals --- Directory.Build.props | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Directory.Build.props b/Directory.Build.props index 4e305e907..a6b4ff332 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -27,6 +27,29 @@ false true + + + + <_Parameter1>$(InternalsVisibleToFriends) + + + + + + + + + + <_Parameter1>%(InternalsVisibleTo.Identity) + + + + + + <_Parameter1>$(AssemblyName)%(InternalsVisibleToSuffix.Identity) + + + true From 6838f4e1cc9353257dcb4033e1167d183fb6aa23 Mon Sep 17 00:00:00 2001 From: Brycen G Date: Fri, 11 Jul 2025 19:58:55 -0400 Subject: [PATCH 11/31] style(Core): run dotnet format --- SnapX.Core/CLI/CLICommand.cs | 14 ++++---------- SnapX.Core/CLI/CLICommandAction.cs | 9 ++------- SnapX.Core/History/HistoryItem.cs | 2 +- SnapX.Core/History/HistorySettings.cs | 2 +- SnapX.Core/Indexer/FolderInfo.cs | 21 ++++++++------------- SnapX.Core/Indexer/HtmlHelper.cs | 4 ++-- SnapX.Core/Utils/ColorHelpers.cs | 2 +- 7 files changed, 19 insertions(+), 35 deletions(-) diff --git a/SnapX.Core/CLI/CLICommand.cs b/SnapX.Core/CLI/CLICommand.cs index 38034bbe3..3426f2203 100644 --- a/SnapX.Core/CLI/CLICommand.cs +++ b/SnapX.Core/CLI/CLICommand.cs @@ -3,18 +3,12 @@ namespace SnapX.Core.CLI; -public class CLICommand +public record CLICommand(string? Command = null, string? Parameter = null) { - public string? Command { get; set; } - public string? Parameter { get; set; } + public string? Command { get; set; } = Command; + public string? Parameter { get; set; } = Parameter; public bool IsCommand { get; set; } // Starts with hyphen? - public CLICommand(string? command = null, string? parameter = null) - { - Command = command; - Parameter = parameter; - } - public bool CheckCommand(string command, StringComparison comparisonType = StringComparison.OrdinalIgnoreCase) { return !string.IsNullOrEmpty(Command) && Command.Equals(command, comparisonType); @@ -22,7 +16,7 @@ public bool CheckCommand(string command, StringComparison comparisonType = Strin public override string? ToString() { - string? text = ""; + var text = ""; if (IsCommand) { diff --git a/SnapX.Core/CLI/CLICommandAction.cs b/SnapX.Core/CLI/CLICommandAction.cs index f2812bf04..5d0918348 100644 --- a/SnapX.Core/CLI/CLICommandAction.cs +++ b/SnapX.Core/CLI/CLICommandAction.cs @@ -3,18 +3,13 @@ namespace SnapX.Core.CLI; -public class CLICommandAction +public record CLICommandAction(params string[] Commands) { - public string[] Commands; + public string[] Commands = Commands; public Action DefaultAction; public Action TextAction; public Action NumberAction; - public CLICommandAction(params string[] commands) - { - Commands = commands; - } - public bool CheckCommands(List commands) { foreach (CLICommand command in commands) diff --git a/SnapX.Core/History/HistoryItem.cs b/SnapX.Core/History/HistoryItem.cs index 8e17d9da8..cc455e736 100644 --- a/SnapX.Core/History/HistoryItem.cs +++ b/SnapX.Core/History/HistoryItem.cs @@ -15,7 +15,7 @@ namespace SnapX.Core.History; internal partial class HistoryContext : JsonSerializerContext; [Table("HistoryItems")] -public class HistoryItem +public record HistoryItem { [Key] public int Id { get; set; } diff --git a/SnapX.Core/History/HistorySettings.cs b/SnapX.Core/History/HistorySettings.cs index d1a3e6e7a..ce9352a3d 100644 --- a/SnapX.Core/History/HistorySettings.cs +++ b/SnapX.Core/History/HistorySettings.cs @@ -4,7 +4,7 @@ namespace SnapX.Core.History; -public class HistorySettings +public record HistorySettings { public bool RememberWindowState { get; set; } = true; public int SplitterDistance { get; set; } = 550; diff --git a/SnapX.Core/Indexer/FolderInfo.cs b/SnapX.Core/Indexer/FolderInfo.cs index 7108b6e32..111e90ea6 100644 --- a/SnapX.Core/Indexer/FolderInfo.cs +++ b/SnapX.Core/Indexer/FolderInfo.cs @@ -2,33 +2,28 @@ // SPDX-License-Identifier: GPL-3.0-or-later +using static System.String; + namespace SnapX.Core.Indexer; -public class FolderInfo +public record FolderInfo(string FolderPath) { - public string FolderPath { get; set; } - public List Files { get; set; } - public List Folders { get; set; } + public string FolderPath { get; set; } = FolderPath; + public List Files { get; set; } = []; + public List Folders { get; set; } = []; public long Size { get; private set; } public int TotalFileCount { get; private set; } public int TotalFolderCount { get; private set; } - public FolderInfo Parent { get; set; } + public FolderInfo? Parent { get; set; } public string FolderName => Path.GetFileName(FolderPath); public bool IsEmpty => TotalFileCount == 0 && TotalFolderCount == 0; - public FolderInfo(string folderPath) - { - FolderPath = folderPath; - Files = []; - Folders = []; - } - public void Update() { Folders.ForEach(x => x.Update()); - Folders.Sort((x, y) => x.FolderName.CompareTo(y.FolderName)); + Folders.Sort((x, y) => Compare(x.FolderName, y.FolderName, StringComparison.Ordinal)); Size = Folders.Sum(x => x.Size) + Files.Sum(x => x.Length); TotalFileCount = Files.Count + Folders.Sum(x => x.TotalFileCount); TotalFolderCount = Folders.Count + Folders.Sum(x => x.TotalFolderCount); diff --git a/SnapX.Core/Indexer/HtmlHelper.cs b/SnapX.Core/Indexer/HtmlHelper.cs index 20bcddf10..aea79303a 100644 --- a/SnapX.Core/Indexer/HtmlHelper.cs +++ b/SnapX.Core/Indexer/HtmlHelper.cs @@ -10,14 +10,14 @@ public static class HtmlHelper { public static string StartTag(string tag, string style = "", string otherFields = "") { - string css = ""; + var css = ""; if (!string.IsNullOrEmpty(style)) { css = $" style=\"{style}\""; } - string fields = ""; + var fields = ""; if (!string.IsNullOrEmpty(otherFields)) { diff --git a/SnapX.Core/Utils/ColorHelpers.cs b/SnapX.Core/Utils/ColorHelpers.cs index 65d704dfd..f93a54887 100644 --- a/SnapX.Core/Utils/ColorHelpers.cs +++ b/SnapX.Core/Utils/ColorHelpers.cs @@ -313,7 +313,7 @@ public static bool ParseColor(string text, out Color color) public static int PerceivedBrightness(Rgba64 color) { - return (int)System.Math.Sqrt((color.R * color.R * .299) + (color.G * color.G * .587) + (color.B * color.B * .114)); + return (int)Math.Sqrt((color.R * color.R * .299) + (color.G * color.G * .587) + (color.B * color.B * .114)); } public static Color VisibleColor(Color color) From 0ccf8b6cf96a5c42d2af9994d627eb19a6308606 Mon Sep 17 00:00:00 2001 From: Brycen G Date: Fri, 11 Jul 2025 20:00:05 -0400 Subject: [PATCH 12/31] refactor: introduce new interfaces --- SnapX.Avalonia/SnapX.Avalonia.csproj | 2 +- SnapX.Avalonia/SnapXAvalonia.cs | 52 ++++++- .../ViewModels/HomePageViewModel.cs | 2 +- SnapX.Avalonia/Views/MainWindow.axaml.cs | 42 ------ SnapX.CLI/Program.cs | 6 +- SnapX.CLI/SnapX.CLI.csproj | 1 + SnapX.Core/CLI/ExternalCLIManager.cs | 87 ++++++----- SnapX.Core/CLI/NativeMessageInput.cs | 2 +- SnapX.Core/CLI/NativeMessagingHost.cs | 26 ++-- SnapX.Core/CLI/SnapXCLIManager.cs | 33 ++--- SnapX.Core/Events.cs | 36 ----- SnapX.Core/History/HistoryFilter.cs | 2 +- SnapX.Core/History/HistoryItem.cs | 60 +------- SnapX.Core/History/HistoryManager.cs | 12 ++ SnapX.Core/History/HistoryManagerSQLite.cs | 29 +++- SnapX.Core/History/ImageHistorySettings.cs | 21 +++ SnapX.Core/Hotkey/Keys.cs | 3 +- SnapX.Core/Indexer/Indexer.cs | 23 ++- SnapX.Core/Indexer/IndexerXml.cs | 28 ++-- SnapX.Core/Interfaces/IDelayService.cs | 6 + SnapX.Core/Interfaces/IFilePicker.cs | 13 ++ SnapX.Core/Interfaces/ILoggerService.cs | 20 +++ SnapX.Core/Interfaces/IMainWindowService.cs | 7 + SnapX.Core/Interfaces/INotificationService.cs | 9 ++ SnapX.Core/Interfaces/IUploadManager.cs | 8 ++ SnapX.Core/Job/TaskHelpers.cs | 49 ++++--- SnapX.Core/Job/TaskInfo.cs | 18 +-- SnapX.Core/Job/TaskSettings.cs | 21 +-- SnapX.Core/Job/WorkerTask.cs | 18 +-- SnapX.Core/Media/ImageBeautifierOptions.cs | 47 ++++++ SnapX.Core/ObservableSink.cs | 31 ++++ SnapX.Core/Services/SerilogLoggerService.cs | 79 ++++++++++ SnapX.Core/SnapX.Core.csproj | 9 +- SnapX.Core/Telemetry.cs | 11 +- SnapX.Core/Upload/UploadManager.cs | 136 +++++++++--------- .../Converters/EnumDescriptionConverter.cs | 39 +++++ .../Converters/EnumProperNameConverter.cs | 38 +++++ .../EnumProperNameKeepCaseConverter.cs | 39 +++++ .../Utils/Converters/MyColorConverter.cs | 42 ++++++ .../StringCollectionToStringTypeConverter.cs | 16 +++ SnapX.Core/Utils/ImageHelpers.cs | 46 +++--- SnapX.Core/Utils/Native/INativeAPI.cs | 21 +++ SnapX.Core/Utils/Native/InputHelpers.cs | 9 -- SnapX.Core/Utils/Native/LinuxAPI.cs | 119 +++++++++------ SnapX.Core/Utils/Native/MacOSAPI.cs | 81 ++++++++--- SnapX.Core/Utils/Native/Methods.cs | 14 +- SnapX.Core/Utils/Native/NativeAPI.cs | 25 ---- SnapX.Core/Utils/Native/WindowsAPI.cs | 2 +- .../Utils/Native/X11ClipboardHandler.cs | 74 ++++------ SnapX.Core/VersionEnforcer.cs | 49 ++++--- SnapX.Core/Watch/WatchFolder.cs | 2 +- SnapX.Core/Watch/WatchFolderManager.cs | 2 +- SnapX.Core/XML/org.freedesktop.DBus.xml | 89 ++++++++++++ SnapX.Core/XML/org.kde.KWin.ScreenShot2.xml | 96 +++++++++++++ SnapX.Core/{ => XML}/wayland.xml | 0 SnapX.NativeMessagingHost/Program.cs | 2 +- .../SnapX.NativeMessagingHost.csproj | 1 + SnapX.sln | 121 +++++++++++----- SnapX.slnx | 5 +- global.json | 2 +- packaging/snapx.spec | 4 + 61 files changed, 1254 insertions(+), 633 deletions(-) delete mode 100644 SnapX.Core/Events.cs create mode 100644 SnapX.Core/History/ImageHistorySettings.cs create mode 100644 SnapX.Core/Interfaces/IDelayService.cs create mode 100644 SnapX.Core/Interfaces/IFilePicker.cs create mode 100644 SnapX.Core/Interfaces/ILoggerService.cs create mode 100644 SnapX.Core/Interfaces/IMainWindowService.cs create mode 100644 SnapX.Core/Interfaces/INotificationService.cs create mode 100644 SnapX.Core/Interfaces/IUploadManager.cs create mode 100644 SnapX.Core/Media/ImageBeautifierOptions.cs create mode 100644 SnapX.Core/ObservableSink.cs create mode 100644 SnapX.Core/Services/SerilogLoggerService.cs create mode 100644 SnapX.Core/Utils/Converters/EnumDescriptionConverter.cs create mode 100644 SnapX.Core/Utils/Converters/EnumProperNameConverter.cs create mode 100644 SnapX.Core/Utils/Converters/EnumProperNameKeepCaseConverter.cs create mode 100644 SnapX.Core/Utils/Converters/MyColorConverter.cs create mode 100644 SnapX.Core/Utils/Converters/StringCollectionToStringTypeConverter.cs create mode 100644 SnapX.Core/Utils/Native/INativeAPI.cs delete mode 100644 SnapX.Core/Utils/Native/InputHelpers.cs delete mode 100644 SnapX.Core/Utils/Native/NativeAPI.cs create mode 100644 SnapX.Core/XML/org.freedesktop.DBus.xml create mode 100644 SnapX.Core/XML/org.kde.KWin.ScreenShot2.xml rename SnapX.Core/{ => XML}/wayland.xml (100%) diff --git a/SnapX.Avalonia/SnapX.Avalonia.csproj b/SnapX.Avalonia/SnapX.Avalonia.csproj index c6454bafb..cb6fbe106 100644 --- a/SnapX.Avalonia/SnapX.Avalonia.csproj +++ b/SnapX.Avalonia/SnapX.Avalonia.csproj @@ -11,6 +11,7 @@ snapx-ui SnapX UI Assets\SnapX_Icon.ico + SnapX.Avalonia.Tests false true @@ -48,7 +49,6 @@ - diff --git a/SnapX.Avalonia/SnapXAvalonia.cs b/SnapX.Avalonia/SnapXAvalonia.cs index edd10612f..0acb7beb3 100644 --- a/SnapX.Avalonia/SnapXAvalonia.cs +++ b/SnapX.Avalonia/SnapXAvalonia.cs @@ -1,3 +1,53 @@ +using CommunityToolkit.Mvvm.DependencyInjection; +using CommunityToolkit.Mvvm.Messaging; +using Microsoft.Extensions.DependencyInjection; +using Serilog; +using SnapX.Avalonia.ViewModels; +using SnapX.Avalonia.Views; +using SnapX.Avalonia.Views.About; +using SnapX.Avalonia.Views.Settings; +using SnapX.Avalonia.Views.Settings.Views; +using SnapX.CommonUI.ViewModels; + namespace SnapX.Avalonia; -public class SnapXAvalonia : Core.SnapX; +public class SnapXAvalonia() : SnapX.Core.SnapX(BuildServices()) +{ + private static IServiceProvider BuildServices() + { + var services = new ServiceCollection(); + Core.SnapX.ConfigureServices(services); + ConfigureServices(services); + var provider = services.BuildServiceProvider(); + + try + { + Ioc.Default.ConfigureServices(provider); + } + catch (Exception ex) + { + Log.Error(ex, "Failed to configure services"); + } + Ioc.Default.AddStaticLogging(); + + return services.BuildServiceProvider(); + } + public static void ConfigureServices(IServiceCollection services) + { + services.AddTransient(); + services.AddSingleton(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + + services.AddTransient(); + services.AddSingleton(); + + services.AddTransient(); + services.AddSingleton(); + + services.AddSingleton(WeakReferenceMessenger.Default); + } +} diff --git a/SnapX.Avalonia/ViewModels/HomePageViewModel.cs b/SnapX.Avalonia/ViewModels/HomePageViewModel.cs index 7adc614e3..808d4aad2 100644 --- a/SnapX.Avalonia/ViewModels/HomePageViewModel.cs +++ b/SnapX.Avalonia/ViewModels/HomePageViewModel.cs @@ -114,7 +114,7 @@ public void RemoveHistoryItem(object Sender) if (Sender is not ListTaskTemplate ltt) return; var task = ltt.task; DebugHelper.WriteLine($"Removing {task.FilePath ?? task.FileName} (Id: {task.Id}) from history"); - var success = TaskManager.History.RemoveHistoryItem(task); + var success = TaskManager.History.RemoveHistoryItems([task]); var status = success ? "Success" : "Failure"; DebugHelper.WriteLine($"{status} removing history item {task.FilePath ?? task.FileName}"); } diff --git a/SnapX.Avalonia/Views/MainWindow.axaml.cs b/SnapX.Avalonia/Views/MainWindow.axaml.cs index 2c3c11ee0..d9a9e67c0 100644 --- a/SnapX.Avalonia/Views/MainWindow.axaml.cs +++ b/SnapX.Avalonia/Views/MainWindow.axaml.cs @@ -1,9 +1,7 @@ using Avalonia; using Avalonia.Controls; -using Avalonia.Interactivity; using Avalonia.Media; using Avalonia.Media.Immutable; -using Avalonia.Platform.Storage; using Avalonia.Styling; using FluentAvalonia.Styling; using FluentAvalonia.UI.Media; @@ -13,7 +11,6 @@ using SnapX.Avalonia.Views.Controls; using SnapX.Core; using SnapX.Core.Job; -using SnapX.Core.Upload; using SnapX.Core.Utils; using Color = Avalonia.Media.Color; @@ -53,48 +50,9 @@ public MainWindow(MainViewModel vm) Position = new PixelPoint(config.MainFormPosition.X, config.MainFormPosition.Y); } InitializeComponent(); - ListenForEvents(); } public MainWindow() : this(new MainViewModel()) { } - public void ListenForEvents() - { - Core.SnapX.EventAggregator.Subscribe(HandleFileSelectionRequested); - } - private async void HandleFileSelectionRequested(NeedFileOpenerEvent @event) - { - var topLevel = TopLevel.GetTopLevel(this); - var files = await topLevel.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions - { - Title = @event.Title, - AllowMultiple = @event.Multiselect, - SuggestedFileName = @event.FileName, - SuggestedStartLocation = await StorageProvider.TryGetFolderFromPathAsync(@event.Directory) - }); - - if (files.Count > 0) - { - string?[] filePaths = files.Select(f => f.Path.ToString()).ToArray(); - UploadManager.UploadFile(filePaths, @event.TaskSettings); - } - } - - // Event handler for the button click - private void OnDemoTestButtonClick(object sender, RoutedEventArgs e) - { - DebugHelper.WriteLine("Upload Demo Image triggered"); - - // try - // { - // var imageUrl = ImageURLTextBox.Text ?? ImageURLTextBox.Watermark; - // UploadManager.DownloadAndUploadFile(imageUrl!); - // } - // catch (Exception ex) - // { - // DebugHelper.Logger.Error(ex.ToString()); - // } - } - private void ApplicationActualThemeVariantChanged(object? sender, EventArgs e) { if (!OperatingSystem.IsWindows()) return; diff --git a/SnapX.CLI/Program.cs b/SnapX.CLI/Program.cs index df201ddb2..b7466aaf3 100644 --- a/SnapX.CLI/Program.cs +++ b/SnapX.CLI/Program.cs @@ -1,10 +1,14 @@ using System.Reflection; +using Microsoft.Extensions.DependencyInjection; using SnapX.CLI; using SnapX.Core; using SnapX.Core.Utils; +var services = new ServiceCollection(); +var provider = services.BuildServiceProvider(); -var snapx = new SnapX.Core.SnapX(); +var snapx = new SnapX.Core.SnapX(provider); +snapx.loadApplicationSettingsPartial(); #if RELEASE snapx.silenceLogging(); #elif DEBUG diff --git a/SnapX.CLI/SnapX.CLI.csproj b/SnapX.CLI/SnapX.CLI.csproj index 88e7f9f61..b3204adff 100644 --- a/SnapX.CLI/SnapX.CLI.csproj +++ b/SnapX.CLI/SnapX.CLI.csproj @@ -10,6 +10,7 @@ true snapx SnapX CLI + SnapX.CLI.Tests diff --git a/SnapX.Core/CLI/ExternalCLIManager.cs b/SnapX.Core/CLI/ExternalCLIManager.cs index 862c1402c..84106b3a6 100644 --- a/SnapX.Core/CLI/ExternalCLIManager.cs +++ b/SnapX.Core/CLI/ExternalCLIManager.cs @@ -13,54 +13,51 @@ public abstract class ExternalCLIManager : IDisposable public bool IsProcessRunning { get; private set; } - protected Process process; + protected Process? process; - public virtual int Open(string? path, string args = null) + public virtual int Open(string? path, string? args = null) { - if (System.IO.File.Exists(path)) + if (!File.Exists(path)) return -1; + using (process = new Process()) { - using (process = new Process()) + var psi = new ProcessStartInfo { - ProcessStartInfo psi = new ProcessStartInfo() - { - FileName = path, - WorkingDirectory = Path.GetDirectoryName(path), - Arguments = args, - UseShellExecute = false, - CreateNoWindow = true, - RedirectStandardInput = true, - RedirectStandardOutput = true, - RedirectStandardError = true, - StandardOutputEncoding = Encoding.UTF8, - StandardErrorEncoding = Encoding.UTF8 - }; - - process.EnableRaisingEvents = true; - if (psi.RedirectStandardOutput) process.OutputDataReceived += cli_OutputDataReceived; - if (psi.RedirectStandardError) process.ErrorDataReceived += cli_ErrorDataReceived; - process.StartInfo = psi; - - Console.WriteLine($"CLI: \"{psi.FileName}\" {psi.Arguments}"); - process.Start(); - - if (psi.RedirectStandardOutput) process.BeginOutputReadLine(); - if (psi.RedirectStandardError) process.BeginErrorReadLine(); - - try - { - IsProcessRunning = true; - process.WaitForExit(); - } - finally - { - IsProcessRunning = false; - } - - return process.ExitCode; + FileName = path, + WorkingDirectory = Path.GetDirectoryName(path), + Arguments = args, + UseShellExecute = false, + CreateNoWindow = true, + RedirectStandardInput = true, + RedirectStandardOutput = true, + RedirectStandardError = true, + StandardOutputEncoding = Encoding.UTF8, + StandardErrorEncoding = Encoding.UTF8 + }; + + process.EnableRaisingEvents = true; + if (psi.RedirectStandardOutput) process.OutputDataReceived += cli_OutputDataReceived; + if (psi.RedirectStandardError) process.ErrorDataReceived += cli_ErrorDataReceived; + process.StartInfo = psi; + + Console.WriteLine($"CLI: \"{psi.FileName}\" {psi.Arguments}"); + process.Start(); + + if (psi.RedirectStandardOutput) process.BeginOutputReadLine(); + if (psi.RedirectStandardError) process.BeginErrorReadLine(); + + try + { + IsProcessRunning = true; + process.WaitForExit(); + } + finally + { + IsProcessRunning = false; } + + return process.ExitCode; } - return -1; } private void cli_OutputDataReceived(object sender, DataReceivedEventArgs e) @@ -81,7 +78,7 @@ private void cli_ErrorDataReceived(object sender, DataReceivedEventArgs e) public void WriteInput(string input) { - if (IsProcessRunning && process != null && process.StartInfo != null && process.StartInfo.RedirectStandardInput) + if (IsProcessRunning && process is { StartInfo.RedirectStandardInput: true }) { process.StandardInput.WriteLine(input); } @@ -97,10 +94,8 @@ public virtual void Close() public void Dispose() { - if (process != null) - { - process.Dispose(); - } + process?.Dispose(); + GC.SuppressFinalize(this); } } diff --git a/SnapX.Core/CLI/NativeMessageInput.cs b/SnapX.Core/CLI/NativeMessageInput.cs index e9254179f..04a6be556 100644 --- a/SnapX.Core/CLI/NativeMessageInput.cs +++ b/SnapX.Core/CLI/NativeMessageInput.cs @@ -4,7 +4,7 @@ namespace SnapX.Core.CLI; -public class NativeMessagingInput +public record NativeMessagingInput { public NativeMessagingAction Action { get; set; } public string? URL { get; set; } diff --git a/SnapX.Core/CLI/NativeMessagingHost.cs b/SnapX.Core/CLI/NativeMessagingHost.cs index bec8e1094..867194258 100644 --- a/SnapX.Core/CLI/NativeMessagingHost.cs +++ b/SnapX.Core/CLI/NativeMessagingHost.cs @@ -5,34 +5,32 @@ using System.Text; namespace SnapX.Core.CLI; -public class NativeMessagingHost +public record NativeMessagingHost { public string Read() { - string input = null; + var input = ""; - Stream inputStream = Console.OpenStandardInput(); + var inputStream = Console.OpenStandardInput(); - byte[] bytesLength = new byte[4]; + var bytesLength = new byte[4]; inputStream.ReadExactly(bytesLength); - int inputLength = BitConverter.ToInt32(bytesLength, 0); + var inputLength = BitConverter.ToInt32(bytesLength, 0); - if (inputLength > 0) - { - byte[] bytesInput = new byte[inputLength]; - inputStream.ReadExactly(bytesInput); - input = Encoding.UTF8.GetString(bytesInput); - } + if (inputLength <= 0) return input; + var bytesInput = new byte[inputLength]; + inputStream.ReadExactly(bytesInput); + input = Encoding.UTF8.GetString(bytesInput); return input; } public void Write(string data) { - Stream outputStream = Console.OpenStandardOutput(); + var outputStream = Console.OpenStandardOutput(); - byte[] bytesData = Encoding.UTF8.GetBytes(data); - byte[] bytesLength = BitConverter.GetBytes(bytesData.Length); + var bytesData = Encoding.UTF8.GetBytes(data); + var bytesLength = BitConverter.GetBytes(bytesData.Length); outputStream.Write(bytesLength, 0, bytesLength.Length); diff --git a/SnapX.Core/CLI/SnapXCLIManager.cs b/SnapX.Core/CLI/SnapXCLIManager.cs index f0d9ef269..5820fe9c9 100644 --- a/SnapX.Core/CLI/SnapXCLIManager.cs +++ b/SnapX.Core/CLI/SnapXCLIManager.cs @@ -5,21 +5,17 @@ namespace SnapX.Core.CLI; -public class SnapXCLIManager : CLIManager +public class SnapXCLIManager(string?[] Arguments) : CLIManager(Arguments) { - public SnapXCLIManager(string?[] arguments) : base(arguments) - { - } - public async Task UseCommandLineArgs() => UseCommandLineArgs(Commands); public async Task UseCommandLineArgs(List commands) { - if (commands != null && commands.Count > 0) + if (commands is { Count: > 0 }) { - TaskSettings taskSettings = FindCLITask(commands); + var taskSettings = FindCLITask(commands); - foreach (CLICommand command in commands) + foreach (var command in commands) { if (command.IsCommand) @@ -45,25 +41,12 @@ await CheckNativeMessagingInput(command)) } } - private TaskSettings FindCLITask(List commands) + private TaskSettings? FindCLITask(List commands) { - if (SnapX.HotkeysConfig != null) - { - CLICommand command = commands.FirstOrDefault(x => x.CheckCommand("task") && !string.IsNullOrEmpty(x.Parameter)); - - if (command != null) - { - foreach (HotkeySettings hotkeySetting in SnapX.HotkeysConfig.Hotkeys) - { - if (command.Parameter == hotkeySetting.TaskSettings.ToString()) - { - return TaskSettings.GetSafeTaskSettings(hotkeySetting.TaskSettings); - } - } - } - } + if (SnapX.HotkeysConfig == null) return null; + var command = commands.FirstOrDefault(x => x.CheckCommand("task") && !string.IsNullOrEmpty(x.Parameter)); - return null; + return command == null ? null : (from hotkeySetting in SnapX.HotkeysConfig.Hotkeys where command.Parameter == hotkeySetting.TaskSettings.ToString() select TaskSettings.GetSafeTaskSettings(hotkeySetting.TaskSettings)).FirstOrDefault(); } private bool CheckCustomUploader(CLICommand command) diff --git a/SnapX.Core/Events.cs b/SnapX.Core/Events.cs deleted file mode 100644 index a330154bb..000000000 --- a/SnapX.Core/Events.cs +++ /dev/null @@ -1,36 +0,0 @@ -using SnapX.Core.Job; -using Xdg.Directories; - -namespace SnapX.Core; - -public class NeedFileOpenerEvent -{ - public string Directory { get; set; } = UserDirectory.PicturesDir; - public string? FileName { get; set; } - public List? AcceptedExtensions { get; set; } - public string? Title { get; set; } = SnapX.AppName; - public bool Multiselect { get; set; } = false; - public TaskSettings TaskSettings { get; set; } -} - -public class NeedRegionCaptureEvent -{ - -} -public class EventAggregator -{ - private readonly List>> _subscriptions = []; - - public void Subscribe(Action action) - { - _subscriptions.Add(Tuple.Create>(typeof(TEvent), (o) => action((TEvent)o))); - } - - public void Publish(TEvent @event) - { - foreach (var subscription in _subscriptions.Where(s => s.Item1 == typeof(TEvent))) - { - subscription.Item2(@event); - } - } -} diff --git a/SnapX.Core/History/HistoryFilter.cs b/SnapX.Core/History/HistoryFilter.cs index af1440246..62acea2bc 100644 --- a/SnapX.Core/History/HistoryFilter.cs +++ b/SnapX.Core/History/HistoryFilter.cs @@ -42,7 +42,7 @@ public IEnumerable ApplyFilter(IEnumerable historyItem string pattern = Regex.Escape(Filename).Replace("\\?", ".").Replace("\\*", ".*"); Regex regex = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); historyItems = historyItems.Where(x => (x.FileName != null && regex.IsMatch(x.FileName)) || - (SearchInTags && x.Tags != null && x.Tags.Any(tag => regex.IsMatch(tag.Text)))); + (SearchInTags && x.Tags != null && x.Tags.Any(tag => regex.IsMatch(tag.Name)))); } if (!string.IsNullOrEmpty(URL)) diff --git a/SnapX.Core/History/HistoryItem.cs b/SnapX.Core/History/HistoryItem.cs index cc455e736..21dbb3dff 100644 --- a/SnapX.Core/History/HistoryItem.cs +++ b/SnapX.Core/History/HistoryItem.cs @@ -33,14 +33,14 @@ public record HistoryItem public record Tag { public int Id { get; set; } - public string? Text { get; set; } - public string? WindowTitle { get; set; } - public string? ProcessName { get; set; } + public required string Name { get; set; } + + public string Value { get; set; } = ""; } public List? Tags { get; set; } = []; public override string ToString() { - string text = ""; + var text = ""; if (!string.IsNullOrEmpty(ShortenedURL)) { @@ -57,6 +57,7 @@ public override string ToString() return text; } + [JsonIgnore] public string TrayMenuText { get @@ -66,59 +67,10 @@ public string TrayMenuText return $"[{DateTime:HH:mm:ss}] {text}"; } } + [JsonIgnore] public string? BestImageSource => !string.IsNullOrWhiteSpace(FilePath) && File.Exists(FilePath) ? FilePath : URL ?? ThumbnailURL; - - public override bool Equals(object? obj) - { - if (obj is not HistoryItem other) - { - return false; - } - - return Id == other.Id && - FileName == other.FileName && - FilePath == other.FilePath && - DateTime == other.DateTime && - Type == other.Type && - Hidden == other.Hidden && - Host == other.Host && - URL == other.URL && - ThumbnailURL == other.ThumbnailURL && - DeletionURL == other.DeletionURL && - ShortenedURL == other.ShortenedURL && - // Deep equality for Tags might be needed if you care about changes within the list - // This gets complex. Often, for lists, you might compare counts and then item-by-item, - // or just rely on a "LastModified" timestamp on the parent object. - (Tags?.SequenceEqual(other.Tags ?? Enumerable.Empty()) ?? (other.Tags == null)); - } - public override int GetHashCode() - { - var hash = new HashCode(); - - hash.Add(Id); - hash.Add(FileName); - hash.Add(FilePath); - hash.Add(DateTime); - hash.Add(Type); - hash.Add(Hidden); - hash.Add(Host); - hash.Add(URL); - hash.Add(ThumbnailURL); - hash.Add(DeletionURL); - hash.Add(ShortenedURL); - - if (Tags != null) - { - foreach (var tag in Tags) - { - hash.Add(tag); - } - } - - return hash.ToHashCode(); - } } diff --git a/SnapX.Core/History/HistoryManager.cs b/SnapX.Core/History/HistoryManager.cs index ca45207ec..1942d1bc2 100644 --- a/SnapX.Core/History/HistoryManager.cs +++ b/SnapX.Core/History/HistoryManager.cs @@ -62,6 +62,18 @@ public virtual bool RemoveHistoryItem(HistoryItem historyItem) return Save(FilePath, allHistoryItems); } + public virtual bool RemoveHistoryItems(HistoryItem[] historyItems) + { + var allHistoryItems = Load(); + foreach (var historyItem in historyItems) + { + var index = allHistoryItems.FindIndex(h => h.Id == historyItem.Id); + if (index == -1) + throw new InvalidOperationException($"History item with ID {historyItem.Id} was not found."); + allHistoryItems.RemoveAt(index); + } + return Save(FilePath, allHistoryItems); + } public virtual async Task> GetHistoryItemsAsync(int Items = int.MaxValue) diff --git a/SnapX.Core/History/HistoryManagerSQLite.cs b/SnapX.Core/History/HistoryManagerSQLite.cs index feb4ede7e..816021f0f 100644 --- a/SnapX.Core/History/HistoryManagerSQLite.cs +++ b/SnapX.Core/History/HistoryManagerSQLite.cs @@ -71,6 +71,30 @@ public override bool RemoveHistoryItem(HistoryItem historyItem) new { historyItem.Id }); return rowsAffected > 0; } + [DapperAot] + public override bool RemoveHistoryItems(HistoryItem[] items) + { + if (items.Length == 0) + return false; + + var allIds = items.Select(x => x.Id).ToArray(); + var deleted = 0; + + using var transaction = _connection.BeginTransaction(); + + for (var i = 0; i < allIds.Length; i += 999) + { + var batch = allIds.Skip(i).Take(999).ToArray(); + var parameters = batch.Select((id, index) => new { Name = $"@id{index}", Value = id }).ToList(); + var sql = $"DELETE FROM HistoryItems WHERE Id IN ({string.Join(", ", parameters.Select(p => p.Name))})"; + var paramDict = parameters.ToDictionary(p => p.Name, p => (object)p.Value); + deleted += _connection.Execute(sql, paramDict, transaction); + } + + transaction.Commit(); + + return deleted > 0; + } [DapperAot] public override HistoryItem UpdateHistoryItem(HistoryItem historyItem) @@ -159,9 +183,8 @@ INSERT INTO HistoryItems (h, t) => new { HistoryItemId = h.Id, - t.Text, - t.WindowTitle, - t.ProcessName + t.Name, + t.Value, }); if (allTags.Any()) diff --git a/SnapX.Core/History/ImageHistorySettings.cs b/SnapX.Core/History/ImageHistorySettings.cs new file mode 100644 index 000000000..7cfe58a07 --- /dev/null +++ b/SnapX.Core/History/ImageHistorySettings.cs @@ -0,0 +1,21 @@ +using SixLabors.ImageSharp; + +namespace SnapX.Core.History; + + +public class WindowState +{ + public Point Location { get; set; } + public Size Size { get; set; } + public bool IsMaximized { get; set; } +} +public class ImageHistorySettings +{ + public bool RememberWindowState { get; set; } = true; + public WindowState WindowState { get; set; } = new(); + public Size ThumbnailSize { get; set; } = new(150, 150); + public int MaxItemCount { get; set; } = 250; + public bool FilterMissingFiles { get; set; } = false; + public bool RememberSearchText { get; set; } = false; + public string SearchText { get; set; } = ""; +} diff --git a/SnapX.Core/Hotkey/Keys.cs b/SnapX.Core/Hotkey/Keys.cs index 18bbe0252..b027c12c9 100644 --- a/SnapX.Core/Hotkey/Keys.cs +++ b/SnapX.Core/Hotkey/Keys.cs @@ -1,5 +1,5 @@ namespace SnapX.Core.Hotkey; - +[Flags] public enum Keys { None = 0, @@ -158,6 +158,7 @@ public enum Keys } +[Flags] public enum Modifiers { None = 0, diff --git a/SnapX.Core/Indexer/Indexer.cs b/SnapX.Core/Indexer/Indexer.cs index b6cdd5aba..07e7d8bd0 100644 --- a/SnapX.Core/Indexer/Indexer.cs +++ b/SnapX.Core/Indexer/Indexer.cs @@ -2,15 +2,14 @@ // SPDX-License-Identifier: GPL-3.0-or-later +using static System.String; + namespace SnapX.Core.Indexer; -public abstract class Indexer +public abstract class Indexer(IndexerSettings IndexerSettings) { - protected IndexerSettings settings = null; - protected Indexer(IndexerSettings indexerSettings) - { - settings = indexerSettings; - } + protected IndexerSettings? settings = IndexerSettings; + public string? Index(string? folderPath) { Indexer indexer = null; @@ -60,27 +59,27 @@ protected Indexer(IndexerSettings indexerSettings) protected FolderInfo GetFolderInfo(string folderPath, int level = 0) { - FolderInfo folderInfo = new FolderInfo(folderPath); + var folderInfo = new FolderInfo(folderPath); if (settings.MaxDepthLevel == 0 || level < settings.MaxDepthLevel) { try { - DirectoryInfo currentDirectoryInfo = new DirectoryInfo(folderPath); + var currentDirectoryInfo = new DirectoryInfo(folderPath); - foreach (DirectoryInfo directoryInfo in currentDirectoryInfo.EnumerateDirectories()) + foreach (var directoryInfo in currentDirectoryInfo.EnumerateDirectories()) { if (settings.SkipHiddenFolders && directoryInfo.Attributes.HasFlag(FileAttributes.Hidden)) { continue; } - FolderInfo subFolderInfo = GetFolderInfo(directoryInfo.FullName, level + 1); + var subFolderInfo = GetFolderInfo(directoryInfo.FullName, level + 1); folderInfo.Folders.Add(subFolderInfo); subFolderInfo.Parent = folderInfo; } - foreach (FileInfo fileInfo in currentDirectoryInfo.EnumerateFiles()) + foreach (var fileInfo in currentDirectoryInfo.EnumerateFiles()) { if (settings.SkipHiddenFiles && fileInfo.Attributes.HasFlag(FileAttributes.Hidden)) { @@ -90,7 +89,7 @@ protected FolderInfo GetFolderInfo(string folderPath, int level = 0) folderInfo.Files.Add(fileInfo); } - folderInfo.Files.Sort((x, y) => x.Name.CompareTo(y.Name)); + folderInfo.Files.Sort((x, y) => Compare(x.Name, y.Name, StringComparison.Ordinal)); } catch (UnauthorizedAccessException) { diff --git a/SnapX.Core/Indexer/IndexerXml.cs b/SnapX.Core/Indexer/IndexerXml.cs index 0b4e1258d..ed9ada1ee 100644 --- a/SnapX.Core/Indexer/IndexerXml.cs +++ b/SnapX.Core/Indexer/IndexerXml.cs @@ -15,26 +15,24 @@ public IndexerXml(IndexerSettings indexerSettings) : base(indexerSettings) public string Index(string folderPath) { - FolderInfo folderInfo = new FolderInfo(folderPath); + var folderInfo = new FolderInfo(folderPath); folderInfo.Update(); - XmlWriterSettings xmlWriterSettings = new XmlWriterSettings(); + var xmlWriterSettings = new XmlWriterSettings(); xmlWriterSettings.Encoding = new UTF8Encoding(false); xmlWriterSettings.ConformanceLevel = ConformanceLevel.Document; xmlWriterSettings.Indent = true; - using (MemoryStream ms = new MemoryStream()) + using var ms = new MemoryStream(); + using (xmlWriter = XmlWriter.Create(ms, xmlWriterSettings)) { - using (xmlWriter = XmlWriter.Create(ms, xmlWriterSettings)) - { - xmlWriter.WriteStartDocument(); - IndexFolder(folderInfo); - xmlWriter.WriteEndDocument(); - xmlWriter.Flush(); - } - - return Encoding.UTF8.GetString(ms.ToArray()); + xmlWriter.WriteStartDocument(); + IndexFolder(folderInfo); + xmlWriter.WriteEndDocument(); + xmlWriter.Flush(); } + + return Encoding.UTF8.GetString(ms.ToArray()); } protected override void IndexFolder(FolderInfo dir, int level = 0) @@ -45,7 +43,7 @@ protected override void IndexFolder(FolderInfo dir, int level = 0) { xmlWriter.WriteStartElement("Files"); - foreach (FileInfo fi in dir.Files) + foreach (var _ in dir.Files) { xmlWriter.WriteStartElement("File"); @@ -59,9 +57,9 @@ protected override void IndexFolder(FolderInfo dir, int level = 0) { xmlWriter.WriteStartElement("Folders"); - foreach (FolderInfo subdir in dir.Folders) + foreach (var subDir in dir.Folders) { - IndexFolder(subdir); + IndexFolder(subDir); } xmlWriter.WriteEndElement(); diff --git a/SnapX.Core/Interfaces/IDelayService.cs b/SnapX.Core/Interfaces/IDelayService.cs new file mode 100644 index 000000000..722a1738e --- /dev/null +++ b/SnapX.Core/Interfaces/IDelayService.cs @@ -0,0 +1,6 @@ +namespace SnapX.Core.Interfaces; + +public interface IDelayService +{ + Task DelayAsync(int milliseconds); +} diff --git a/SnapX.Core/Interfaces/IFilePicker.cs b/SnapX.Core/Interfaces/IFilePicker.cs new file mode 100644 index 000000000..0b642c349 --- /dev/null +++ b/SnapX.Core/Interfaces/IFilePicker.cs @@ -0,0 +1,13 @@ +namespace SnapX.Core.Interfaces; + +public interface IFilePicker +{ + /// + /// Prompts the user to select one or more files. + /// + /// Dialog title. + /// Optional initial directory. + /// Allow selecting multiple files. + /// Array of selected file paths, or empty array if cancelled. + Task PickFilesAsync(string title, string initialDirectory, bool allowMultiple); +} diff --git a/SnapX.Core/Interfaces/ILoggerService.cs b/SnapX.Core/Interfaces/ILoggerService.cs new file mode 100644 index 000000000..875cc83de --- /dev/null +++ b/SnapX.Core/Interfaces/ILoggerService.cs @@ -0,0 +1,20 @@ +using Serilog.Core; + +namespace SnapX.Core.Interfaces; + +public interface ILoggerService +{ + ILogScope BeginScope(string name); + [MessageTemplateFormatMethod("messageTemplate")] + void Debug(string messageTemplate, params object[] propertyValues); + [MessageTemplateFormatMethod("messageTemplate")] + void Information(string messageTemplate, params object[] propertyValues); + [MessageTemplateFormatMethod("messageTemplate")] + void Warning(string messageTemplate, params object[] propertyValues); + [MessageTemplateFormatMethod("messageTemplate")] + void Error(string messageTemplate, params object[] propertyValues); + [MessageTemplateFormatMethod("messageTemplate")] + void Error(Exception exception, string messageTemplate, params object[] propertyValues); +} + +public interface ILogScope : IDisposable; diff --git a/SnapX.Core/Interfaces/IMainWindowService.cs b/SnapX.Core/Interfaces/IMainWindowService.cs new file mode 100644 index 000000000..cf1231ae5 --- /dev/null +++ b/SnapX.Core/Interfaces/IMainWindowService.cs @@ -0,0 +1,7 @@ +namespace SnapX.Core.SharpCapture.Interfaces; + +public interface IMainWindowService +{ + Task HideAsync(); + Task ForceActivateAsync(); +} diff --git a/SnapX.Core/Interfaces/INotificationService.cs b/SnapX.Core/Interfaces/INotificationService.cs new file mode 100644 index 000000000..54873aebc --- /dev/null +++ b/SnapX.Core/Interfaces/INotificationService.cs @@ -0,0 +1,9 @@ +using SnapX.Core.Job; + +namespace SnapX.Core.Interfaces; + +public interface INotificationService +{ + Task CloseActiveFormAsync(); + Task PlayNotificationSoundAsync(NotificationSound sound, TaskSettings settings); +} diff --git a/SnapX.Core/Interfaces/IUploadManager.cs b/SnapX.Core/Interfaces/IUploadManager.cs new file mode 100644 index 000000000..a15df2c1d --- /dev/null +++ b/SnapX.Core/Interfaces/IUploadManager.cs @@ -0,0 +1,8 @@ +using SnapX.Core.Job; + +namespace SnapX.Core.Interfaces; + +public interface IUploadManager +{ + Task RunImageTaskAsync(TaskMetadata metadata, TaskSettings taskSettings); +} diff --git a/SnapX.Core/Job/TaskHelpers.cs b/SnapX.Core/Job/TaskHelpers.cs index ce0051772..bcdd08732 100644 --- a/SnapX.Core/Job/TaskHelpers.cs +++ b/SnapX.Core/Job/TaskHelpers.cs @@ -22,11 +22,10 @@ using SixLabors.ImageSharp.Formats.Tiff; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; -using SnapX.Core.Capture; using SnapX.Core.CLI; using SnapX.Core.ImageEffects; using SnapX.Core.Media; -using SnapX.Core.ScreenCapture; +using SnapX.Core.SharpCapture; using SnapX.Core.Upload; using SnapX.Core.Upload.Custom; using SnapX.Core.Upload.SharingServices; @@ -47,12 +46,12 @@ public static async Task ExecuteJob(HotkeyType job, CLICommand command = null) await ExecuteJob(SnapX.DefaultTaskSettings, job, command); } - public static async Task ExecuteJob(TaskSettings taskSettings) + public static async Task ExecuteJob(TaskSettings? taskSettings) { await ExecuteJob(taskSettings, taskSettings.Job); } - public static async Task ExecuteJob(TaskSettings taskSettings, HotkeyType job, CLICommand command = null) + public static async Task ExecuteJob(TaskSettings? taskSettings, HotkeyType job, CLICommand command = null) { if (job == HotkeyType.None) return; @@ -100,31 +99,31 @@ public static async Task ExecuteJob(TaskSettings taskSettings, HotkeyType job, C break; // Screen capture case HotkeyType.PrintScreen: - new CaptureFullscreen().Capture(safeTaskSettings); + // new CaptureFullscreen().CaptureAsync(safeTaskSettings); break; case HotkeyType.ActiveWindow: - new CaptureActiveWindow().Capture(safeTaskSettings); + // new CaptureActiveWindow().CaptureAsync(safeTaskSettings); break; case HotkeyType.ActiveMonitor: - new CaptureActiveMonitor().Capture(safeTaskSettings); + // new CaptureActiveMonitor().CaptureAsync(safeTaskSettings); break; case HotkeyType.RectangleRegion: - new CaptureRegion().Capture(safeTaskSettings); + // new CaptureRegion().CaptureAsync(safeTaskSettings); break; case HotkeyType.RectangleLight: - new CaptureRegion(RegionCaptureType.Light).Capture(safeTaskSettings); + // new CaptureRegion(RegionCaptureType.Light).Capture(safeTaskSettings); break; case HotkeyType.RectangleTransparent: - new CaptureRegion(RegionCaptureType.Transparent).Capture(safeTaskSettings); + // new CaptureRegion(RegionCaptureType.Transparent).Capture(safeTaskSettings); break; case HotkeyType.CustomRegion: - new CaptureCustomRegion().Capture(safeTaskSettings); + // new CaptureCustomRegion().Capture(safeTaskSettings); break; case HotkeyType.CustomWindow: - new CaptureCustomWindow().Capture(safeTaskSettings); + // new CaptureCustomWindow().Capture(safeTaskSettings); break; case HotkeyType.LastRegion: - new CaptureLastRegion().Capture(safeTaskSettings); + // new CaptureLastRegion().Capture(safeTaskSettings); break; case HotkeyType.ScrollingCapture: DebugHelper.WriteException("HotkeyType.ScrollingCapture is NOT implemented."); @@ -321,7 +320,7 @@ public static async Task ExecuteJob(TaskSettings taskSettings, HotkeyType job, C } } - public static ImageData PrepareImage(Image img, TaskSettings taskSettings) + public static ImageData PrepareImage(Image img, TaskSettings? taskSettings) { var imageData = new ImageData(); imageData.ImageStream = SaveImageAsStream(img, taskSettings.ImageSettings.ImageFormat, taskSettings); @@ -371,7 +370,7 @@ public static ImageData PrepareImage(Image img, TaskSettings taskSettings) // return null; // } - public static MemoryStream SaveImageAsStream(Image img, EImageFormat imageFormat, TaskSettings taskSettings) + public static MemoryStream SaveImageAsStream(Image img, EImageFormat imageFormat, TaskSettings? taskSettings) { return SaveImageAsStream(img, imageFormat, taskSettings.ImageSettings.ImagePNGBitDepth, taskSettings.ImageSettings.ImageJPEGQuality, taskSettings.ImageSettings.ImageGIFQuality); @@ -417,7 +416,7 @@ public static MemoryStream SaveImageAsStream(Image image, EImageFormat imageForm return ms; } - public static void SaveImageAsFile(Image img, TaskSettings taskSettings, bool overwriteFile = false) + public static void SaveImageAsFile(Image img, TaskSettings? taskSettings, bool overwriteFile = false) { using (ImageData imageData = PrepareImage(img, taskSettings)) { @@ -437,7 +436,7 @@ public static void SaveImageAsFile(Image img, TaskSettings taskSettings, bool ov } } } - public static string? HandleExistsFile(string? filePath, TaskSettings taskSettings) + public static string? HandleExistsFile(string? filePath, TaskSettings? taskSettings) { if (File.Exists(filePath)) { @@ -457,18 +456,18 @@ public static void SaveImageAsFile(Image img, TaskSettings taskSettings, bool ov return filePath; } - public static string? HandleExistsFile(string? folderPath, string? fileName, TaskSettings taskSettings) + public static string? HandleExistsFile(string? folderPath, string? fileName, TaskSettings? taskSettings) { var filePath = Path.Combine(folderPath, fileName); return HandleExistsFile(filePath, taskSettings); } - public static string? GetFileName(TaskSettings taskSettings, string extension, Image bmp) + public static string? GetFileName(TaskSettings? taskSettings, string extension, Image bmp) { var metadata = new TaskMetadata(bmp); return GetFileName(taskSettings, extension, metadata); } - public static string? GetFileName(TaskSettings taskSettings, string extension = null, TaskMetadata metadata = null) + public static string? GetFileName(TaskSettings? taskSettings, string extension = null, TaskMetadata metadata = null) { string? fileName; @@ -511,7 +510,7 @@ public static void SaveImageAsFile(Image img, TaskSettings taskSettings, bool ov return fileName; } - public static string? GetScreenshotsFolder(TaskSettings taskSettings = null, TaskMetadata metadata = null, DateTime? date = null) + public static string? GetScreenshotsFolder(TaskSettings? taskSettings = null, TaskMetadata metadata = null, DateTime? date = null) { date ??= DateTime.Now; var dt = date.Value; @@ -753,7 +752,7 @@ public static async Task OCRImage(Image? image = null, string? filePath return result.Text; } - public static void PinToScreen(TaskSettings taskSettings = null) + public static void PinToScreen(TaskSettings? taskSettings = null) { throw new NotImplementedException("PinToScreen is not implemented"); } @@ -763,7 +762,7 @@ public static void TweetMessage() throw new NotImplementedException("TweetMessage is not implemented"); } - public static EDataType FindDataType(string? filePath, TaskSettings taskSettings) + public static EDataType FindDataType(string? filePath, TaskSettings? taskSettings) { if (FileHelpers.CheckExtension(filePath, taskSettings.AdvancedSettings.ImageExtensions)) { @@ -796,7 +795,7 @@ public static bool CheckFFmpeg(TaskSettings taskSettings) return true; } - public static Screenshot GetScreenshot(TaskSettings taskSettings = null) + public static Screenshot GetScreenshot(TaskSettings? taskSettings = null) { if (taskSettings == null) taskSettings = TaskSettings.GetDefaultTaskSettings(); @@ -909,7 +908,7 @@ public static void ImportImageEffect(string? json) } } - public static async Task HandleNativeMessagingInput(string? filePath, TaskSettings taskSettings = null) + public static async Task HandleNativeMessagingInput(string? filePath, TaskSettings? taskSettings = null) { if (!string.IsNullOrEmpty(filePath) && File.Exists(filePath)) { diff --git a/SnapX.Core/Job/TaskInfo.cs b/SnapX.Core/Job/TaskInfo.cs index 7faf072a2..bf143ba64 100644 --- a/SnapX.Core/Job/TaskInfo.cs +++ b/SnapX.Core/Job/TaskInfo.cs @@ -10,9 +10,9 @@ using SnapX.Core.Utils.Extensions; namespace SnapX.Core.Job; -public class TaskInfo +public record TaskInfo { - public TaskSettings TaskSettings { get; set; } + public TaskSettings? TaskSettings { get; set; } public string Status { get; set; } public TaskJob Job { get; set; } @@ -128,12 +128,9 @@ public string UploaderHost public UploadResult Result { get; set; } - public TaskInfo(TaskSettings taskSettings) + public TaskInfo(TaskSettings? taskSettings = null) { - if (taskSettings == null) - { - taskSettings = TaskSettings.GetDefaultTaskSettings(); - } + taskSettings ??= TaskSettings.GetDefaultTaskSettings(); TaskSettings = taskSettings; Metadata = new TaskMetadata(); @@ -149,16 +146,15 @@ public TaskInfo(TaskSettings taskSettings) if (!string.IsNullOrEmpty(Metadata.WindowTitle)) { - tags.Add(new HistoryItem.Tag { Text = Metadata.WindowTitle }); + tags.Add(new HistoryItem.Tag { Name = "WindowTitle", Value = Metadata.WindowTitle }); } - // Add ProcessName tag if present if (!string.IsNullOrEmpty(Metadata.ProcessName)) { - tags.Add(new HistoryItem.Tag { Text = Metadata.ProcessName }); + tags.Add(new HistoryItem.Tag { Name = "ProcessName", Value = Metadata.ProcessName }); } - return tags.Count != 0 ? tags : null; + return tags.Count != 0 ? tags : []; } diff --git a/SnapX.Core/Job/TaskSettings.cs b/SnapX.Core/Job/TaskSettings.cs index 4ff4caf29..30718d8ab 100644 --- a/SnapX.Core/Job/TaskSettings.cs +++ b/SnapX.Core/Job/TaskSettings.cs @@ -7,7 +7,8 @@ using System.Text.Json.Serialization; using SixLabors.ImageSharp; using SnapX.Core.Indexer; -using SnapX.Core.ScreenCapture; +using SnapX.Core.Media; +using SnapX.Core.SharpCapture; using SnapX.Core.Upload; using SnapX.Core.Utils; using SnapX.Core.Utils.Extensions; @@ -18,7 +19,7 @@ namespace SnapX.Core.Job; public class TaskSettings { [JsonIgnore] - public TaskSettings TaskSettingsReference { get; private set; } + public TaskSettings? TaskSettingsReference { get; private set; } [JsonIgnore] public bool IsSafeTaskSettings => TaskSettingsReference != null; @@ -132,17 +133,17 @@ public bool IsUsingDefaultSettings } } - public static TaskSettings GetDefaultTaskSettings() + public static TaskSettings? GetDefaultTaskSettings() { - TaskSettings taskSettings = new TaskSettings(); + var taskSettings = new TaskSettings(); taskSettings.SetDefaultSettings(); taskSettings.TaskSettingsReference = SnapX.DefaultTaskSettings; return taskSettings; } - public static TaskSettings GetSafeTaskSettings(TaskSettings taskSettings) + public static TaskSettings? GetSafeTaskSettings(TaskSettings? taskSettings) { - TaskSettings safeTaskSettings; + TaskSettings? safeTaskSettings; if (taskSettings.IsUsingDefaultSettings && SnapX.DefaultTaskSettings != null) { @@ -164,7 +165,7 @@ public void SetDefaultSettings() { if (SnapX.DefaultTaskSettings != null) { - TaskSettings defaultTaskSettings = SnapX.DefaultTaskSettings.Copy(); + TaskSettings? defaultTaskSettings = SnapX.DefaultTaskSettings.Copy(); if (UseDefaultAfterCaptureJob) { @@ -369,7 +370,7 @@ public class TaskSettingsCapture // public FFmpegOptions FFmpegOptions = new FFmpegOptions(); public int ScreenRecordFPS = 30; public int GIFFPS = 15; - public RegionCaptureOptions SurfaceOptions = new RegionCaptureOptions(); + public RegionCaptureOptions SurfaceOptions = new(); public bool ScreenRecordShowCursor = true; public bool ScreenRecordAutoStart = true; public float ScreenRecordStartDelay = 0f; @@ -431,13 +432,13 @@ public class TaskSettingsTools public string ScreenColorPickerFormat = "$hex"; public string ScreenColorPickerFormatCtrl = "$r255, $g255, $b255"; public string ScreenColorPickerInfoText = "RGB: $r255, $g255, $b255$nHex: $hex$nX: $x Y: $y"; - public PinToScreenOptions PinToScreenOptions = new(); + // public PinToScreenOptions PinToScreenOptions = new(); public IndexerSettings IndexerSettings = new(); public ImageBeautifierOptions ImageBeautifierOptions = new(); public ImageCombinerOptions ImageCombinerOptions = new(); public VideoConverterOptions VideoConverterOptions = new(); public VideoThumbnailOptions VideoThumbnailOptions = new(); - public BorderlessWindowSettings BorderlessWindowSettings = new(); + // public BorderlessWindowSettings BorderlessWindowSettings = new(); } public class TaskSettingsAdvanced diff --git a/SnapX.Core/Job/WorkerTask.cs b/SnapX.Core/Job/WorkerTask.cs index d8efdcbd9..147ebcaf1 100644 --- a/SnapX.Core/Job/WorkerTask.cs +++ b/SnapX.Core/Job/WorkerTask.cs @@ -51,13 +51,13 @@ public class WorkerTask : IDisposable #region Constructors - private WorkerTask(TaskSettings taskSettings) + private WorkerTask(TaskSettings? taskSettings) { Status = TaskStatus.InQueue; Info = new TaskInfo(taskSettings); } - public static WorkerTask CreateDataUploaderTask(EDataType dataType, Stream stream, string? fileName, TaskSettings taskSettings) + public static WorkerTask CreateDataUploaderTask(EDataType dataType, Stream stream, string? fileName, TaskSettings? taskSettings) { WorkerTask task = new WorkerTask(taskSettings); task.Info.Job = TaskJob.DataUpload; @@ -67,7 +67,7 @@ public static WorkerTask CreateDataUploaderTask(EDataType dataType, Stream strea return task; } - public static WorkerTask CreateFileUploaderTask(string? filePath, TaskSettings taskSettings) + public static WorkerTask CreateFileUploaderTask(string? filePath, TaskSettings? taskSettings) { WorkerTask task = new WorkerTask(taskSettings); task.Info.FilePath = filePath; @@ -98,7 +98,7 @@ public static WorkerTask CreateFileUploaderTask(string? filePath, TaskSettings t return task; } - public static WorkerTask CreateImageUploaderTask(TaskMetadata metadata, TaskSettings taskSettings, string customFileName = null) + public static WorkerTask CreateImageUploaderTask(TaskMetadata metadata, TaskSettings? taskSettings, string customFileName = null) { WorkerTask task = new WorkerTask(taskSettings); task.Info.Job = TaskJob.Job; @@ -118,7 +118,7 @@ public static WorkerTask CreateImageUploaderTask(TaskMetadata metadata, TaskSett return task; } - public static WorkerTask CreateTextUploaderTask(string? text, TaskSettings taskSettings) + public static WorkerTask CreateTextUploaderTask(string? text, TaskSettings? taskSettings) { WorkerTask task = new WorkerTask(taskSettings); task.Info.Job = TaskJob.TextUpload; @@ -128,7 +128,7 @@ public static WorkerTask CreateTextUploaderTask(string? text, TaskSettings taskS return task; } - public static WorkerTask CreateURLShortenerTask(string? url, TaskSettings taskSettings) + public static WorkerTask CreateURLShortenerTask(string? url, TaskSettings? taskSettings) { WorkerTask task = new WorkerTask(taskSettings); task.Info.Job = TaskJob.ShortenURL; @@ -138,7 +138,7 @@ public static WorkerTask CreateURLShortenerTask(string? url, TaskSettings taskSe return task; } - public static WorkerTask CreateShareURLTask(string? url, TaskSettings taskSettings) + public static WorkerTask CreateShareURLTask(string? url, TaskSettings? taskSettings) { WorkerTask task = new WorkerTask(taskSettings); task.Info.Job = TaskJob.ShareURL; @@ -148,7 +148,7 @@ public static WorkerTask CreateShareURLTask(string? url, TaskSettings taskSettin return task; } - public static WorkerTask CreateFileJobTask(string? filePath, TaskMetadata metadata, TaskSettings taskSettings, string customFileName = null) + public static WorkerTask CreateFileJobTask(string? filePath, TaskMetadata metadata, TaskSettings? taskSettings, string customFileName = null) { var task = new WorkerTask(taskSettings); task.Info.FilePath = filePath; @@ -176,7 +176,7 @@ public static WorkerTask CreateFileJobTask(string? filePath, TaskMetadata metada return task; } - public static WorkerTask CreateDownloadTask(string? url, bool upload, TaskSettings taskSettings) + public static WorkerTask CreateDownloadTask(string? url, bool upload, TaskSettings? taskSettings) { WorkerTask task = new WorkerTask(taskSettings); task.Info.Job = upload ? TaskJob.DownloadUpload : TaskJob.Download; diff --git a/SnapX.Core/Media/ImageBeautifierOptions.cs b/SnapX.Core/Media/ImageBeautifierOptions.cs new file mode 100644 index 000000000..a8fa37aea --- /dev/null +++ b/SnapX.Core/Media/ImageBeautifierOptions.cs @@ -0,0 +1,47 @@ +using SixLabors.ImageSharp; + +namespace SnapX.Core.Media; + +public class ImageBeautifierOptions +{ + public int Margin { get; set; } + public int Padding { get; set; } + public bool SmartPadding { get; set; } + public int RoundedCorner { get; set; } + public int ShadowRadius { get; set; } + public int ShadowOpacity { get; set; } + public int ShadowDistance { get; set; } + public int ShadowAngle { get; set; } + public Color ShadowColor { get; set; } + public ImageBeautifierBackgroundType BackgroundType { get; set; } + public GradientInfo BackgroundGradient { get; set; } + public Color BackgroundColor { get; set; } + public string BackgroundImageFilePath { get; set; } + + public ImageBeautifierOptions() + { + ResetOptions(); + } + + public void ResetOptions() + { + Margin = 80; + Padding = 40; + SmartPadding = true; + RoundedCorner = 20; + ShadowRadius = 30; + ShadowOpacity = 80; + ShadowDistance = 10; + ShadowAngle = 180; + ShadowColor = Color.Black; + BackgroundType = ImageBeautifierBackgroundType.Gradient; + BackgroundGradient = new GradientInfo( + LinearGradientMode.Horizontal, + Color.FromRgba(255, 81, 47, 255), + Color.FromRgba(221, 36, 118, 255) + ); + + BackgroundColor = Color.FromRgba(34, 34, 34, 255); + BackgroundImageFilePath = ""; + } +} diff --git a/SnapX.Core/ObservableSink.cs b/SnapX.Core/ObservableSink.cs new file mode 100644 index 000000000..a4285b718 --- /dev/null +++ b/SnapX.Core/ObservableSink.cs @@ -0,0 +1,31 @@ +using Serilog.Core; +using Serilog.Events; + +namespace SnapX.Core; + +public class ObservableSink(IFormatProvider? FormatProvider = null) : ILogEventSink +{ + private readonly List _buffer = []; + private readonly Lock _lock = new(); + + public event EventHandler? LogMessageReceived; + + public void Emit(LogEvent logEvent) + { + + lock (_lock) + { + _buffer.Add(logEvent); + } + + LogMessageReceived?.Invoke(this, logEvent); + } + + public List GetBufferedEvents() + { + lock (_lock) + { + return _buffer; + } + } +} diff --git a/SnapX.Core/Services/SerilogLoggerService.cs b/SnapX.Core/Services/SerilogLoggerService.cs new file mode 100644 index 000000000..a70c7b86c --- /dev/null +++ b/SnapX.Core/Services/SerilogLoggerService.cs @@ -0,0 +1,79 @@ +using Microsoft.Extensions.Configuration; +using Serilog; +using Serilog.Context; +using Serilog.Sinks.SystemConsole.Themes; +using SnapX.Core.Interfaces; + +namespace SnapX.Core.Services; +public class SerilogLogService : ILoggerService +{ + private readonly ILogger _logger; + + public SerilogLogService( + string? logFilePath, + bool logToConsole, + IConfiguration? config = null) + { + var loggerConfig = new LoggerConfiguration(); + +#if DEBUG + loggerConfig.MinimumLevel.Debug(); +#else + loggerConfig.MinimumLevel.Information(); +#endif + + if (!string.IsNullOrWhiteSpace(logFilePath)) + { + loggerConfig = loggerConfig + .WriteTo.Async(a => a.File( + logFilePath, + rollingInterval: RollingInterval.Day, + buffered: true, + outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}]: {Message:lj}{NewLine}{Exception}" + )); + } + + if (logToConsole) + { + loggerConfig = loggerConfig + .WriteTo.Console(theme: AnsiConsoleTheme.Sixteen); + } + + if (config is not null) + { + loggerConfig.ReadFrom.Configuration(config); + } + + _logger = loggerConfig.CreateLogger(); + } + + public SerilogLogService(ILogger Logger) + { + _logger = Logger; + } + public ILogScope BeginScope(string name) + { + return new SerilogLogScope(LogContext.PushProperty("Scope", name)); + } + public void Debug(string messageTemplate, params object[] args) => + _logger.Debug(messageTemplate, args); + + public void Information(string messageTemplate, params object[] args) => + _logger.Information(messageTemplate, args); + + public void Warning(string messageTemplate, params object[] args) => + _logger.Warning(messageTemplate, args); + + public void Error(Exception exception, string messageTemplate, params object[] args) => + _logger.Error(exception, messageTemplate, args); + + public void Error(string messageTemplate, params object[] args) => + _logger.Error(messageTemplate, args); + private class SerilogLogScope(IDisposable InnerScope) : ILogScope + { + public void Dispose() + { + InnerScope.Dispose(); + } + } +} diff --git a/SnapX.Core/SnapX.Core.csproj b/SnapX.Core/SnapX.Core.csproj index 414d75c4d..f8fbd9ef1 100644 --- a/SnapX.Core/SnapX.Core.csproj +++ b/SnapX.Core/SnapX.Core.csproj @@ -9,7 +9,7 @@ 3.1.0.54 4.11.0.34 2.1.11 - 9.0.6 + 9.0.7 @@ -79,6 +79,7 @@ while these are only useful for Linux, hiding them behind a compiler conditional makes debugging more difficult. --> + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -119,7 +120,7 @@ - + @@ -127,9 +128,7 @@ - - - + diff --git a/SnapX.Core/Telemetry.cs b/SnapX.Core/Telemetry.cs index bfe79675e..00c481bfb 100644 --- a/SnapX.Core/Telemetry.cs +++ b/SnapX.Core/Telemetry.cs @@ -1,9 +1,9 @@ -using System.Diagnostics.CodeAnalysis; -using System.Text.Json; +using System.Text.Json; using System.Text.Json.Serialization; using Aptabase.Core; using Dapper; using Microsoft.Data.Sqlite; +using SnapX.Core.Interfaces; using SnapX.Core.Utils; namespace SnapX.Core; @@ -43,7 +43,7 @@ internal partial class SentryContext : JsonSerializerContext; [JsonSerializable(typeof(OsInfo.GenericGraphicsInfo))] internal partial class AptabaseContext : JsonSerializerContext; -public sealed class Telemetry(SqliteConnection Connection, AptabaseClient AptabaseClient) +public sealed class Telemetry(SqliteConnection Connection, AptabaseClient AptabaseClient, ILoggerService Logger) { [DapperAot] public void LogTelemetry(string provider, string eventName, string envelope) @@ -60,14 +60,11 @@ INSERT INTO TelemetryLog (EventName, Provider, Envelope) } catch (Exception ex) { - // Do not use DebugHelper.WriteException, that will call this function again! - DebugHelper.WriteLine($"Telemetry Logger Error: {ex.Message}"); - DebugHelper.WriteLine(ex.ToString()); + Logger.Error("Telemetry Logger Error: {ExMessage}", ex.ToString()); } }); } - [RequiresUnreferencedCode("Uses reflection to access properties that may be removed by the trimmer.")] public void TrackEvent(string EventName, Dictionary? Envelope = null) { if (string.IsNullOrWhiteSpace(EventName)) return; diff --git a/SnapX.Core/Upload/UploadManager.cs b/SnapX.Core/Upload/UploadManager.cs index 69f10251c..97bf67cdd 100644 --- a/SnapX.Core/Upload/UploadManager.cs +++ b/SnapX.Core/Upload/UploadManager.cs @@ -5,7 +5,7 @@ using System.Runtime.InteropServices; using System.Web; using SixLabors.ImageSharp; -using SixLabors.ImageSharp.PixelFormats; +using SnapX.Core.Interfaces; using SnapX.Core.Job; using SnapX.Core.Utils; using SnapX.Core.Utils.Extensions; @@ -14,11 +14,17 @@ namespace SnapX.Core.Upload; -public static class UploadManager +public class UploadManager { + private static IFilePicker _filePicker; + + public UploadManager(IFilePicker filePicker) + { + _filePicker = filePicker; + } public static void UploadFile(string? filePath, TaskSettings? taskSettings = null) { - if (taskSettings == null) taskSettings = TaskSettings.GetDefaultTaskSettings(); + taskSettings ??= TaskSettings.GetDefaultTaskSettings(); if (!string.IsNullOrEmpty(filePath)) { @@ -72,16 +78,25 @@ private static bool IsUploadConfirmed(int length) public static void UploadFile(TaskSettings? taskSettings = null) { taskSettings ??= TaskSettings.GetDefaultTaskSettings(); - var data = new NeedFileOpenerEvent() - { - Title = Lang.UploadManagerUploadFile, - Multiselect = true, - Directory = IsValidDirectory(SnapX.Settings.FileUploadDefaultDirectory) ? SnapX.Settings.FileUploadDefaultDirectory : UserDirectory.DesktopDir, - TaskSettings = taskSettings - }; + var title = Lang.UploadManagerUploadFile; + var initialDir = IsValidDirectory(SnapX.Settings.FileUploadDefaultDirectory) + ? SnapX.Settings.FileUploadDefaultDirectory + : UserDirectory.DesktopDir; + DebugHelper.WriteLine("Need file to upload. Asking UI for file."); - // The UI will now do the rest. - SnapX.EventAggregator.Publish(data); + var selectedFiles = _filePicker.PickFilesAsync( + title, + initialDir, + allowMultiple: true).GetAwaiter().GetResult(); + + if (selectedFiles.Length == 0) + { + DebugHelper.WriteLine("User cancelled file picker."); + return; + } + + DebugHelper.WriteLine($"User selected {selectedFiles.Length} file(s) to upload."); + UploadFile(selectedFiles); } public static bool IsValidDirectory(string? dir) @@ -89,7 +104,7 @@ public static bool IsValidDirectory(string? dir) return !string.IsNullOrEmpty(dir) && Directory.Exists(dir); } - public static void UploadFolder(TaskSettings taskSettings = null) + public static void UploadFolder(TaskSettings? taskSettings = null) { // using (FolderSelectDialog folderDialog = new FolderSelectDialog()) // { @@ -112,7 +127,7 @@ public static void UploadFolder(TaskSettings taskSettings = null) // } } - public static void ProcessImageUpload(Image image, TaskSettings taskSettings) + public static void ProcessImageUpload(Image image, TaskSettings? taskSettings) { if (image != null) { @@ -125,7 +140,7 @@ public static void ProcessImageUpload(Image image, TaskSettings taskSettings) } } - public static void ProcessTextUpload(string? text, TaskSettings taskSettings) + public static void ProcessTextUpload(string? text, TaskSettings? taskSettings) { if (string.IsNullOrEmpty(text)) return; @@ -163,7 +178,7 @@ public static void ProcessTextUpload(string? text, TaskSettings taskSettings) } } - public static void ProcessFilesUpload(string?[] files, TaskSettings taskSettings) + public static void ProcessFilesUpload(string?[] files, TaskSettings? taskSettings) { if (files?.Length > 0) { @@ -172,19 +187,15 @@ public static void ProcessFilesUpload(string?[] files, TaskSettings taskSettings } - public static void ClipboardUpload(TaskSettings taskSettings = null) + public static void ClipboardUpload(TaskSettings? taskSettings = null) { - if (taskSettings == null) taskSettings = TaskSettings.GetDefaultTaskSettings(); + taskSettings ??= TaskSettings.GetDefaultTaskSettings(); try { if (Clipboard.ContainsImage()) { - Image image; - - - image = Clipboard.GetImage(); - + var image = Clipboard.GetImage(); ProcessImageUpload(image, taskSettings); } @@ -214,9 +225,9 @@ public static void ClipboardUpload(TaskSettings taskSettings = null) } } - public static void UploadURL(TaskSettings taskSettings = null, string? url = null) + public static void UploadURL(TaskSettings? taskSettings = null, string? url = null) { - if (taskSettings == null) taskSettings = TaskSettings.GetDefaultTaskSettings(); + taskSettings ??= TaskSettings.GetDefaultTaskSettings(); string? inputText = null; @@ -233,22 +244,22 @@ public static void UploadURL(TaskSettings taskSettings = null, string? url = nul DownloadAndUploadFile(url, taskSettings); } } - public static void RunImageTask(Image image, TaskSettings taskSettings) + public static void RunImageTask(Image image, TaskSettings? taskSettings) { var metadata = new TaskMetadata(image); RunImageTask(metadata, taskSettings); } - public static void RunImageTask(Image image, TaskSettings taskSettings, bool skipQuickTaskMenu = false, bool skipAfterCaptureWindow = false) + public static void RunImageTask(Image image, TaskSettings? taskSettings, bool skipQuickTaskMenu = false, bool skipAfterCaptureWindow = false) { var metadata = new TaskMetadata(image); RunImageTask(metadata, taskSettings, skipQuickTaskMenu, skipAfterCaptureWindow); } - public static void RunImageTask(TaskMetadata metadata, TaskSettings taskSettings, bool skipQuickTaskMenu = false, bool skipAfterCaptureWindow = false) + public static void RunImageTask(TaskMetadata metadata, TaskSettings? taskSettings, bool skipQuickTaskMenu = false, bool skipAfterCaptureWindow = false) { - if (taskSettings == null) taskSettings = TaskSettings.GetDefaultTaskSettings(); + taskSettings ??= TaskSettings.GetDefaultTaskSettings(); - if (metadata != null && metadata.Image != null && taskSettings != null) + if (metadata is { Image: not null } && taskSettings != null) { if (!skipQuickTaskMenu && taskSettings.AfterCaptureJob.HasFlag(AfterCaptureTasks.ShowQuickTaskMenu)) { @@ -264,45 +275,34 @@ public static void RunImageTask(TaskMetadata metadata, TaskSettings taskSettings } } - public static void UploadImage(Image image, TaskSettings taskSettings = null) + public static void UploadImage(Image? image, TaskSettings? taskSettings = null) { - if (image != null) + taskSettings ??= TaskSettings.GetDefaultTaskSettings(); + if (image == null) return; + if (taskSettings is { IsSafeTaskSettings: true }) { - if (taskSettings == null) - { - taskSettings = TaskSettings.GetDefaultTaskSettings(); - } - - if (taskSettings.IsSafeTaskSettings) - { - taskSettings.UseDefaultAfterCaptureJob = false; - taskSettings.AfterCaptureJob = AfterCaptureTasks.UploadImageToHost; - } - - RunImageTask(image, taskSettings); + taskSettings.UseDefaultAfterCaptureJob = false; + taskSettings.AfterCaptureJob = AfterCaptureTasks.UploadImageToHost; } + + RunImageTask(image, taskSettings); } - public static void UploadImage(Image image, ImageDestination imageDestination, FileDestination imageFileDestination, TaskSettings taskSettings = null) + public static void UploadImage(Image? image, ImageDestination imageDestination, FileDestination imageFileDestination, TaskSettings? taskSettings = null) { - if (image != null) - { - if (taskSettings == null) - { - taskSettings = TaskSettings.GetDefaultTaskSettings(); - } - - if (taskSettings.IsSafeTaskSettings) - { - taskSettings.UseDefaultAfterCaptureJob = false; - taskSettings.AfterCaptureJob = AfterCaptureTasks.UploadImageToHost; - taskSettings.UseDefaultDestinations = false; - taskSettings.ImageDestination = imageDestination; - taskSettings.ImageFileDestination = imageFileDestination; - } + if (image == null) return; + taskSettings ??= TaskSettings.GetDefaultTaskSettings(); - RunImageTask(image, taskSettings); + if (taskSettings is { IsSafeTaskSettings: true }) + { + taskSettings.UseDefaultAfterCaptureJob = false; + taskSettings.AfterCaptureJob = AfterCaptureTasks.UploadImageToHost; + taskSettings.UseDefaultDestinations = false; + taskSettings.ImageDestination = imageDestination; + taskSettings.ImageFileDestination = imageFileDestination; } + + RunImageTask(image, taskSettings); } public static void UploadText(string? text, TaskSettings? taskSettings = null, bool allowCustomText = false) { @@ -312,11 +312,11 @@ public static void UploadText(string? text, TaskSettings? taskSettings = null, b if (allowCustomText) { - string input = taskSettings.AdvancedSettings.TextCustom; + var input = taskSettings?.AdvancedSettings.TextCustom; if (!string.IsNullOrEmpty(input)) { - if (taskSettings.AdvancedSettings.TextCustomEncodeInput) + if (taskSettings is { AdvancedSettings.TextCustomEncodeInput: true }) { text = HttpUtility.HtmlEncode(text); } @@ -329,7 +329,7 @@ public static void UploadText(string? text, TaskSettings? taskSettings = null, b TaskManager.Start(task); } - public static void UploadImageStream(Stream stream, string? fileName, TaskSettings taskSettings = null) + public static void UploadImageStream(Stream? stream, string? fileName, TaskSettings? taskSettings = null) { taskSettings ??= TaskSettings.GetDefaultTaskSettings(); @@ -341,7 +341,7 @@ public static void UploadImageStream(Stream stream, string? fileName, TaskSettin } - public static void ShortenURL(string? url, TaskSettings taskSettings = null) + public static void ShortenURL(string? url, TaskSettings? taskSettings = null) { if (string.IsNullOrEmpty(url)) return; @@ -365,7 +365,7 @@ public static void ShortenURL(string? url, UrlShortenerType urlShortener) } - public static void ShareURL(string? url, TaskSettings taskSettings = null) + public static void ShareURL(string? url, TaskSettings? taskSettings = null) { if (string.IsNullOrEmpty(url)) return; @@ -389,10 +389,10 @@ public static void ShareURL(string? url, URLSharingServices urlSharingService) TaskManager.Start(task); } - public static void DownloadFile(string? url, TaskSettings taskSettings = null) + public static void DownloadFile(string? url, TaskSettings? taskSettings = null) => DownloadFile(url, false, taskSettings); - public static void DownloadAndUploadFile(string? url, TaskSettings taskSettings = null) + public static void DownloadAndUploadFile(string? url, TaskSettings? taskSettings = null) => DownloadFile(url, true, taskSettings); private static void DownloadFile(string? url, bool upload, TaskSettings? taskSettings = null) diff --git a/SnapX.Core/Utils/Converters/EnumDescriptionConverter.cs b/SnapX.Core/Utils/Converters/EnumDescriptionConverter.cs new file mode 100644 index 000000000..e5b9f6d3b --- /dev/null +++ b/SnapX.Core/Utils/Converters/EnumDescriptionConverter.cs @@ -0,0 +1,39 @@ +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using SnapX.Core.Utils.Extensions; + +namespace SnapX.Core.Utils.Converters; + +public class EnumDescriptionConverter(Type Type) : EnumConverter(Type) +{ + private readonly Type enumType = Type; + + public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destType) + { + return destType == typeof(string); + } + + public override object ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destType) + { + return ((Enum)value!).GetLocalizedDescription(); + } + + public override bool CanConvertFrom(ITypeDescriptorContext? context, Type srcType) + { + return srcType == typeof(string); + } + [RequiresUnreferencedCode("Uses Enum.GetValues")] + public override object ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value) + { + foreach (var e in Enum.GetValues(enumType).OfType()) + { + if (e.GetLocalizedDescription() == (string)value) + { + return e; + } + } + + return Enum.Parse(enumType, (string)value); + } +} diff --git a/SnapX.Core/Utils/Converters/EnumProperNameConverter.cs b/SnapX.Core/Utils/Converters/EnumProperNameConverter.cs new file mode 100644 index 000000000..513d2219c --- /dev/null +++ b/SnapX.Core/Utils/Converters/EnumProperNameConverter.cs @@ -0,0 +1,38 @@ +using System.ComponentModel; +using System.Globalization; + +namespace SnapX.Core.Utils.Converters; + +public class EnumProperNameConverter(Type Type) : EnumConverter(Type) +{ + private readonly Type enumType = Type; + + public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destType) + { + return destType == typeof(string); + } + + public override object ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destType) + { + ArgumentNullException.ThrowIfNull(value); + return Helpers.GetProperName(value.ToString()!); + } + + public override bool CanConvertFrom(ITypeDescriptorContext? context, Type srcType) + { + return srcType == typeof(string); + } + + public override object ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value) + { + foreach (Enum e in Enum.GetValues(enumType).OfType()) + { + if (Helpers.GetProperName(e.ToString()) == (string)value) + { + return e; + } + } + + return Enum.Parse(enumType, (string)value); + } +} diff --git a/SnapX.Core/Utils/Converters/EnumProperNameKeepCaseConverter.cs b/SnapX.Core/Utils/Converters/EnumProperNameKeepCaseConverter.cs new file mode 100644 index 000000000..c2e9b737c --- /dev/null +++ b/SnapX.Core/Utils/Converters/EnumProperNameKeepCaseConverter.cs @@ -0,0 +1,39 @@ +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; + +namespace SnapX.Core.Utils.Converters; + +public class EnumProperNameKeepCaseConverter(Type Type) : EnumConverter(Type) +{ + private Type enumType = Type; + + public override bool CanConvertTo(ITypeDescriptorContext context, Type destType) + { + return destType == typeof(string); + } + + public override object ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destType) + { + return Helpers.GetProperName(value.ToString(), true); + } + + public override bool CanConvertFrom(ITypeDescriptorContext? context, Type srcType) + { + return srcType == typeof(string); + } + + [RequiresUnreferencedCode("Uses Enum.GetValues")] + public override object ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value) + { + foreach (Enum e in Enum.GetValues(enumType).OfType()) + { + if (Helpers.GetProperName(e.ToString(), true) == (string)value) + { + return e; + } + } + + return Enum.Parse(enumType, (string)value); + } +} diff --git a/SnapX.Core/Utils/Converters/MyColorConverter.cs b/SnapX.Core/Utils/Converters/MyColorConverter.cs new file mode 100644 index 000000000..01702e878 --- /dev/null +++ b/SnapX.Core/Utils/Converters/MyColorConverter.cs @@ -0,0 +1,42 @@ +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using SixLabors.ImageSharp; + +namespace SnapX.Core.Utils.Converters; + +public class MyColorConverter : TypeConverter +{ + public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType) + { + return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object ConvertFrom(ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) + { + if (value is string colorStr) + { + // Try to parse named color first (e.g. "Red") + var knownColor = TryParseKnownColor(colorStr); + if (knownColor is not null) + { + return knownColor.Value; + } + + // Try parse hex value (#RRGGBB or #AARRGGBB) + return colorStr.StartsWith("#") ? Color.ParseHex(colorStr) : throw new FormatException($"Cannot convert '{colorStr}' to ImageSharp Color."); + } + + return base.ConvertFrom(context, culture, value) ?? throw new FormatException($"Cannot convert '{value}' to ImageSharp Color."); + } + [UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "")] + [RequiresUnreferencedCode("Checks SixLabors predefined colors")] + private Color? TryParseKnownColor(string name) + { + var colorProperty = typeof(Color).GetProperty(name, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); + if (colorProperty is not null && colorProperty.PropertyType == typeof(Color)) + { + return (Color)colorProperty.GetValue(null)!; + } + return null; + } +} diff --git a/SnapX.Core/Utils/Converters/StringCollectionToStringTypeConverter.cs b/SnapX.Core/Utils/Converters/StringCollectionToStringTypeConverter.cs new file mode 100644 index 000000000..102f1b7dc --- /dev/null +++ b/SnapX.Core/Utils/Converters/StringCollectionToStringTypeConverter.cs @@ -0,0 +1,16 @@ +using System.ComponentModel; +using System.Globalization; + +namespace SnapX.Core.Utils.UITypeEditors; + +public class StringCollectionToStringTypeConverter : TypeConverter +{ + public override object ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType) + { + ArgumentNullException.ThrowIfNull(value); + if (destinationType != typeof(string)) return base.ConvertTo(context, culture, value, destinationType) ?? throw new FormatException($"Cannot convert '{value}' to ImageSharp Color."); + var list = (List)value; + return string.Join(", ", list); + + } +} diff --git a/SnapX.Core/Utils/ImageHelpers.cs b/SnapX.Core/Utils/ImageHelpers.cs index 326f3f65a..552367f66 100644 --- a/SnapX.Core/Utils/ImageHelpers.cs +++ b/SnapX.Core/Utils/ImageHelpers.cs @@ -27,29 +27,22 @@ internal static Image ImageDataToImage(uniffi.snapxrust.ImageData imageData) => Image.LoadPixelData(imageData.image, (int)imageData.width, (int)imageData.height); public static Size ApplyAspectRatio(int width, int height, Image img) { - // Get the original aspect ratio of the image - float aspectRatio = (float)img.Width / img.Height; + var aspectRatio = (float)img.Width / img.Height; - // Determine the target aspect ratio (width to height ratio) - float targetAspectRatio = (float)width / height; + var targetAspectRatio = (float)width / height; - // Variables to hold the new width and height - int newWidth = width; - int newHeight = height; + var newWidth = width; + var newHeight = height; - // Adjust the size based on the aspect ratio comparison if (aspectRatio > targetAspectRatio) { - // The image is wider than the target aspect ratio, so adjust based on width - newHeight = (int)(width / aspectRatio); // Calculate new height to maintain aspect ratio + newHeight = (int)(width / aspectRatio); } else if (aspectRatio < targetAspectRatio) { - // The image is taller than the target aspect ratio, so adjust based on height - newWidth = (int)(height * aspectRatio); // Calculate new width to maintain aspect ratio + newWidth = (int)(height * aspectRatio); } - // Return the new size that maintains the aspect ratio return new Size(newWidth, newHeight); } // See how clean the code is?! @@ -57,7 +50,7 @@ public static Size ApplyAspectRatio(int width, int height, Image img) // BLESSED. public static Image ResizeImage(Image img, Size TargetSize, bool preserveAspectRatio = false, bool fill = false, Color? growFillColor = null) { - if (growFillColor == null) growFillColor = Color.Transparent; + growFillColor ??= Color.Transparent; // Mutate the image to apply resizing and fill (if necessary) img.Mutate(ctx => { @@ -431,7 +424,24 @@ public static Image DrawReflection( return finalImage; } - + /// + /// Fills the image with a checkerboard pattern. + /// + public static void DrawCheckerPattern(Image image, int cellSize, Color[] colors) + { + image.Mutate(ctx => + { + for (var y = 0; y < image.Height; y += cellSize) + { + for (var x = 0; x < image.Width; x += cellSize) + { + var isEven = ((x / cellSize) + (y / cellSize)) % 2 == 0; + var color = isEven ? colors[0] : colors[1]; + ctx.Fill(color, new RectangleF(x, y, cellSize, cellSize)); + } + } + }); + } private static float[] CreateAlphaGradient(int height, float maxAlpha, float minAlpha) { float[] gradient = new float[height]; @@ -618,14 +628,10 @@ public static Color GetMostCommonColor(Rgba32[] pixelRow) foreach (var pixel in pixelRow) { var color = new Rgba32(pixel.R, pixel.G, pixel.B); - if (colorCounts.ContainsKey(color)) + if (!colorCounts.TryAdd(color, 1)) { colorCounts[color]++; } - else - { - colorCounts[color] = 1; - } } // Find the color with the maximum count diff --git a/SnapX.Core/Utils/Native/INativeAPI.cs b/SnapX.Core/Utils/Native/INativeAPI.cs new file mode 100644 index 000000000..256030773 --- /dev/null +++ b/SnapX.Core/Utils/Native/INativeAPI.cs @@ -0,0 +1,21 @@ +using SixLabors.ImageSharp; +using SnapX.Core.Media; + +namespace SnapX.Core.Utils.Native; + +// Secure, Contain, & Protect. +public interface INativeAPI +{ + void ShowWindow(WindowInfo windowInfo); + void ShowWindow(IntPtr hwnd); + Image GetJumboFileIcon(string filePath, bool jumboSize = true); + void HideWindow(WindowInfo windowInfo); + void HideWindow(IntPtr handle); + List GetWindowList(); + void CopyText(string text); + void CopyImage(Image image, string? fileName); + Rectangle GetWindowRectangle(WindowInfo window); + Rectangle GetWindowRectangle(IntPtr windowHandle); + Point GetCursorPosition(); + Screen? GetScreen(Point pos); +} diff --git a/SnapX.Core/Utils/Native/InputHelpers.cs b/SnapX.Core/Utils/Native/InputHelpers.cs deleted file mode 100644 index e47370d55..000000000 --- a/SnapX.Core/Utils/Native/InputHelpers.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace SnapX.Core.Utils.Native; - -public static class InputHelpers -{ - public static void SendKeyPress() - { - - } -} diff --git a/SnapX.Core/Utils/Native/LinuxAPI.cs b/SnapX.Core/Utils/Native/LinuxAPI.cs index ab1ac7fc9..6539fb8b2 100644 --- a/SnapX.Core/Utils/Native/LinuxAPI.cs +++ b/SnapX.Core/Utils/Native/LinuxAPI.cs @@ -3,12 +3,13 @@ using SixLabors.ImageSharp; using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.PixelFormats; +using SnapX.Core.Interfaces; using SnapX.Core.Media; using WaylandSharp; namespace SnapX.Core.Utils.Native; -public partial class LinuxAPI : NativeAPI +public partial class LinuxAPI(ILoggerService Logger) : INativeAPI { private const string LibX11 = "libX11.so.6"; @@ -31,12 +32,17 @@ internal static bool IsGNOME() && sessionVersion.Contains("gnome", StringComparison.OrdinalIgnoreCase); } - public override Rectangle GetWindowRectangle(IntPtr windowHandle) + public Rectangle GetWindowRectangle(WindowInfo window) + { + return GetWindowRectangleX11(window.Handle); + } + + public Rectangle GetWindowRectangle(IntPtr windowHandle) { return GetWindowRectangleX11(windowHandle); } - public override Screen? GetScreen(Point pos) + public Screen? GetScreen(Point pos) { var display = XOpenDisplay(null); if (display == IntPtr.Zero) @@ -63,7 +69,7 @@ out _ if (pos.X < x || pos.X > x + (int)width || pos.Y < y || pos.Y > y + (int)height) continue; - DebugHelper.Logger?.Debug("Point {Pos} is within screen {I} bounds", pos, i); + Logger.Debug("Point {Pos} is within screen {I} bounds", pos, i); return new Screen() { Bounds = new Rectangle(x, y, (int)width, (int)height), @@ -76,22 +82,47 @@ out _ return null; } - public override List GetWindowList() + public void ShowWindow(WindowInfo windowInfo) + { + throw new NotImplementedException(); + } + + public void ShowWindow(IntPtr hwnd) + { + throw new NotImplementedException(); + } + + public Image GetJumboFileIcon(string filePath, bool jumboSize = true) + { + throw new NotImplementedException(); + } + + public void HideWindow(WindowInfo windowInfo) + { + throw new NotImplementedException(); + } + + public void HideWindow(IntPtr handle) + { + throw new NotImplementedException(); + } + + public List GetWindowList() { var windows = new List(); if (IsWayland()) { - if (IsPlasma()) - { - // Interact with Plasmashell over DBus - return windows; - } - - if (IsGNOME()) - { - // Interact with GNOME Shell - return windows; - } + // if (IsPlasma()) + // { + // // Interact with Plasmashell over DBus + // return windows; + // } + // + // if (IsGNOME()) + // { + // // Interact with GNOME Shell + // return windows; + // } return windows; } @@ -99,7 +130,7 @@ public override List GetWindowList() var display = XOpenDisplay(null); if (display == IntPtr.Zero) { - DebugHelper.Logger?.Debug("Unable to open X display"); + Logger.Debug("Unable to open X display"); return windows; } @@ -116,7 +147,7 @@ out var nchildren ); if (status == 0) { - DebugHelper.Logger?.Debug("XQueryTree failed"); + Logger.Debug("XQueryTree failed"); XCloseDisplay(display); return windows; } @@ -280,7 +311,7 @@ private static bool IsWindowMinimized(IntPtr display, IntPtr hwnd) private const long ALL_PLANES = -1; public const int ZPIXMAP = 2; - internal static Image TakeScreenshotWithX11(Screen screen) + internal Image TakeScreenshotWithX11(Screen screen) { unsafe { @@ -306,18 +337,18 @@ internal static Image TakeScreenshotWithX11(Screen screen) } XGetWindowAttributes(display, rootWindow, out var attributes); - DebugHelper.Logger?.Debug("x: {AttributesX}", attributes.x); - DebugHelper.Logger?.Debug("y: {AttributesY}", attributes.y); - DebugHelper.Logger?.Debug("width: {AttributesWidth}", attributes.width); - DebugHelper.Logger?.Debug("height: {AttributesHeight}", attributes.height); - DebugHelper.Logger?.Debug( + Logger.Debug("x: {AttributesX}", attributes.x); + Logger.Debug("y: {AttributesY}", attributes.y); + Logger.Debug("width: {AttributesWidth}", attributes.width); + Logger.Debug("height: {AttributesHeight}", attributes.height); + Logger.Debug( "border_width: {AttributesBorderWidth}", attributes.border_width ); - DebugHelper.Logger?.Debug("depth: {AttributesDepth}", attributes.depth); - DebugHelper.Logger?.Debug("visual: {AttributesVisual}", attributes.visual); - DebugHelper.Logger?.Debug("root: {AttributesRoot}", attributes.root); - DebugHelper.Logger?.Debug("colormap: {AttributesColormap}", attributes.colormap); + Logger.Debug("depth: {AttributesDepth}", attributes.depth); + Logger.Debug("visual: {AttributesVisual}", attributes.visual); + Logger.Debug("root: {AttributesRoot}", attributes.root); + Logger.Debug("colormap: {AttributesColormap}", attributes.colormap); var screenBounds = screen.Bounds; var imagePtr = XGetImage( @@ -346,8 +377,8 @@ internal static Image TakeScreenshotWithX11(Screen screen) // For simplicity, assuming a direct byte copy is feasible for common ZPIXMAP depths (e.g., 24 or 32 bits). var bytesPerPixel = xImage.depth / 8; var pixelDataSize = xImage.width * xImage.height * bytesPerPixel; - DebugHelper.Logger?.Debug("bytesPerPixel: {bytesPerPixel}", bytesPerPixel); - DebugHelper.Logger?.Debug("pixelDataSize: {pixelDataSize}", pixelDataSize); + Logger.Debug("bytesPerPixel: {BytesPerPixel}", bytesPerPixel); + Logger.Debug("pixelDataSize: {PixelDataSize}", pixelDataSize); // Create a byte array to hold the pixel data var pixelData = new byte[pixelDataSize]; @@ -530,7 +561,7 @@ public struct XSelectionRequestEvent // private static readonly IntPtr XA_PRIMARY = 1; internal const IntPtr XA_CLIPBOARD = 2; - public override void CopyText(string text) + public void CopyText(string text) { if (IsWayland()) { @@ -562,7 +593,7 @@ public override void CopyText(string text) var display = XOpenDisplay(null); if (display == IntPtr.Zero) { - DebugHelper.Logger?.Debug("Unable to open X11 display"); + Logger.Debug("Unable to open X11 display"); return; } var root = XDefaultRootWindow(display); @@ -643,7 +674,7 @@ public Rectangle GetScreenBounds() } } - public override void CopyImage(Image image, string? filename) + public void CopyImage(Image image, string? filename) { using var ms = new MemoryStream(); // Save the image in a format that ImageSharp understands for re-loading/processing @@ -657,7 +688,7 @@ public override void CopyImage(Image image, string? filename) if (IsWayland()) { - DebugHelper.Logger?.Debug("LinuxAPI.CopyImage - Wayland only code"); + Logger.Debug("LinuxAPI.CopyImage - Wayland only code"); // For Wayland, you'd need wl-clipboard or similar native Wayland protocols. // This X11 implementation does not apply to Wayland. // return; @@ -666,12 +697,12 @@ public override void CopyImage(Image image, string? filename) try { // Get the singleton instance of the clipboard handler and set the image - X11ClipboardHandler.Instance.SetImage(imageForClipboard, filename); - DebugHelper.Logger?.Debug("X11 image clipboard initiated."); + new X11ClipboardHandler(Logger).SetImage(imageForClipboard, filename); + Logger.Debug("X11 image clipboard initiated"); } catch (Exception ex) { - DebugHelper.Logger?.Error($"Failed to set X11 clipboard image: {ex.Message}"); + Logger.Error("Failed to set X11 clipboard image: {ExMessage}", ex.Message); } } @@ -681,13 +712,7 @@ private static Rectangle GetWindowRectangleX11(IntPtr windowHandle) if (display == IntPtr.Zero) throw new InvalidOperationException("Unable to open X11 display."); - var attributes = new XWindowAttributes(); - if (XGetWindowAttributes(display, windowHandle, out attributes) != 0) - { - return new Rectangle(attributes.x, attributes.y, attributes.width, attributes.height); - } - - throw new InvalidOperationException("Unable to get window attributes."); + return XGetWindowAttributes(display, windowHandle, out var attributes) != 0 ? new Rectangle(attributes.x, attributes.y, attributes.width, attributes.height) : throw new InvalidOperationException("Unable to get window attributes."); } [LibraryImport(LibX11)] @@ -703,9 +728,9 @@ internal static partial int XQueryPointer( out int mask ); - public override Point GetCursorPosition() + public Point GetCursorPosition() { - DebugHelper.Logger?.Debug("Get cursor position"); + Logger.Debug("Get cursor position"); var display = XOpenDisplay(null); if (display == IntPtr.Zero) { @@ -729,7 +754,7 @@ out var mask ); XCloseDisplay(display); - DebugHelper.Logger?.Debug( + Logger.Debug( "Cursor position: {RootX}, {RootY}, {WinX}, {WinY}, {Mask}", rootX, rootY, diff --git a/SnapX.Core/Utils/Native/MacOSAPI.cs b/SnapX.Core/Utils/Native/MacOSAPI.cs index 1c82e836a..d2a69bf7e 100644 --- a/SnapX.Core/Utils/Native/MacOSAPI.cs +++ b/SnapX.Core/Utils/Native/MacOSAPI.cs @@ -3,10 +3,11 @@ using System.Text.RegularExpressions; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Formats.Jpeg; +using SnapX.Core.Media; namespace SnapX.Core.Utils.Native; -public class MacOSAPI : NativeAPI +public partial class MacOSAPI : INativeAPI { private static string GenerateFastString(int length) { @@ -17,13 +18,12 @@ private static string GenerateFastString(int length) result[i] = chars[random.Next(chars.Length)]; return new string(result); } - public override void CopyImage(Image image) - { - CopyImage(image, GenerateFastString(8) + ".png"); - } + private const string CoreGraphics = "/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics"; - public override void CopyImage(Image image, string? fileName) + + public void CopyImage(Image image, string? fileName) { + fileName ??= GenerateFastString(8) + ".png"; var tempPath = Path.Combine(Path.GetTempPath(), $"{Path.GetFileNameWithoutExtension(fileName)}.jpg"); image.Save(tempPath, new JpegEncoder()); var appleScript = $"set the clipboard to (read (POSIX file \"{tempPath}\") as JPEG picture)"; @@ -51,30 +51,65 @@ public override void CopyImage(Image image, string? fileName) File.Delete(tempPath); } + public Rectangle GetWindowRectangle(WindowInfo window) + { + throw new NotImplementedException(); + } + + public Rectangle GetWindowRectangle(IntPtr windowHandle) + { + throw new NotImplementedException(); + } + + + public void ShowWindow(WindowInfo windowInfo) + { + throw new NotImplementedException(); + } + + public void ShowWindow(IntPtr hwnd) + { + throw new NotImplementedException(); + } + + public Image GetJumboFileIcon(string filePath, bool jumboSize = true) + { + throw new NotImplementedException(); + } + + public void HideWindow(WindowInfo windowInfo) + { + throw new NotImplementedException(); + } - public override void CopyText(string text) + public void HideWindow(IntPtr handle) + { + throw new NotImplementedException(); + } + + public List GetWindowList() + { + throw new NotImplementedException(); + } + public void CopyText(string text) { // Escape quotes in the text to ensure AppleScript handles them correctly // 1. Escape double quotes by replacing `"` with `""` for AppleScript var escapedText = text.Replace("\"", "\"\""); - // 2. Escape backslashes by replacing `\` with `\\` (for C# string formatting) - escapedText = "\"" + Regex.Replace(escapedText, @"(\\+)$", @"$1$1") + "\""; ; + // 2. Escape backslashes by replacing `\` with `\\` + escapedText = "\"" + Regex.Replace(escapedText, @"(\\+)$", @"$1$1") + "\""; - // Properly format the AppleScript to set the clipboard var appleScript = $"set the clipboard to \"{escapedText}\""; - // Create the process to execute the AppleScript var process = new Process(); process.StartInfo.FileName = "osascript"; process.StartInfo.Arguments = $"-e \"{appleScript}\""; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.UseShellExecute = false; - // Start the process process.Start(); - // Wait for the process to finish process.WaitForExit(); } [StructLayout(LayoutKind.Sequential)] @@ -83,19 +118,23 @@ struct CGPoint public double X; public double Y; } + [LibraryImport(CoreGraphics)] + private static partial CGPoint CGEventGetLocation(IntPtr eventRef); - [DllImport("/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics")] - static extern CGPoint CGEventGetLocation(IntPtr eventRef); - - [DllImport("/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics")] - static extern IntPtr CGEventCreate(IntPtr source); - [DllImport("/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics")] - static extern IntPtr CFRelease(IntPtr eventRef); - public override Point GetCursorPosition() + [LibraryImport(CoreGraphics)] + private static partial IntPtr CGEventCreate(IntPtr source); + [LibraryImport(CoreGraphics)] + private static partial void CFRelease(IntPtr eventRef); + public Point GetCursorPosition() { var ev = CGEventCreate(IntPtr.Zero); var point = CGEventGetLocation(ev); CFRelease(ev); return new Point((int)point.X, (int)point.Y); } + + public Screen? GetScreen(Point pos) + { + throw new NotImplementedException(); + } } diff --git a/SnapX.Core/Utils/Native/Methods.cs b/SnapX.Core/Utils/Native/Methods.cs index 3e7f0726e..40c322ac7 100644 --- a/SnapX.Core/Utils/Native/Methods.cs +++ b/SnapX.Core/Utils/Native/Methods.cs @@ -1,23 +1,26 @@ using SixLabors.ImageSharp; +using SnapX.Core.Interfaces; using SnapX.Core.Media; using SnapX.Core.SharpCapture; using SnapX.Core.SharpCapture.Linux; using SnapX.Core.SharpCapture.macOS; +using SnapX.Core.Utils.Extensions; #if TARGET_WINDOWS using SnapX.Core.SharpCapture.Windows; #endif namespace SnapX.Core.Utils.Native; -public static class Methods +public class Methods(ILoggerService _logger) { + private ILoggerService Logger => _logger; private static bool IsMacOS => OperatingSystem.IsMacOS(); private static bool IsLinux => OperatingSystem.IsLinux(); private static bool IsWindows => OperatingSystem.IsWindows(); private static bool IsFreeBSD => OperatingSystem.IsFreeBSD(); - internal static NativeAPI NativeAPI + internal static INativeAPI NativeAPI { get { @@ -25,12 +28,12 @@ internal static NativeAPI NativeAPI return new WindowsAPI(); #else if (IsMacOS) return new MacOSAPI(); - if (IsLinux || IsFreeBSD) return new LinuxAPI(); + if (IsLinux || IsFreeBSD) return new LinuxAPI(DebugHelper.Logger as ILoggerService); throw new PlatformNotSupportedException("This platform is not supported for native API calls."); #endif } } - private static BaseCapture SharpCapture + private static BaseSharpCapture SharpCapture { get { @@ -44,7 +47,6 @@ private static BaseCapture SharpCapture } } public static List GetWindowList() => NativeAPI.GetWindowList(); - public static Image GetJumboFileIcon(string filePath, bool jumboSize = true) => NativeAPI.GetJumboFileIcon(filePath, jumboSize); public static void ShowWindow(WindowInfo window) => NativeAPI.ShowWindow(window); @@ -75,7 +77,7 @@ public static Point GetCursorPosition() } catch (Exception ex) { - DebugHelper.Logger.Warning(ex.ToString()); + ex.ShowError(); } DebugHelper.WriteLine($"GetCursorPosition returned {point}"); return point; diff --git a/SnapX.Core/Utils/Native/NativeAPI.cs b/SnapX.Core/Utils/Native/NativeAPI.cs deleted file mode 100644 index 5107f4465..000000000 --- a/SnapX.Core/Utils/Native/NativeAPI.cs +++ /dev/null @@ -1,25 +0,0 @@ -using SixLabors.ImageSharp; -using SnapX.Core.Media; - -namespace SnapX.Core.Utils.Native; - -// Secure, Contain, & Protect. -public class NativeAPI -{ - public virtual void ShowWindow(WindowInfo windowInfo) => throw new NotImplementedException("NativeAPI.ShowWindow is not implemented."); - - public virtual void ShowWindow(IntPtr hwnd) => throw new NotImplementedException("NativeAPI.ShowWindow is not implemented."); - public virtual Image GetJumboFileIcon(string filePath, bool jumboSize = true) => throw new NotImplementedException("NativeAPI.GetJumboFileIcon is not implemented."); - public virtual void HideWindow(WindowInfo windowInfo) => throw new NotImplementedException("NativeAPI.HideWindow is not implemented."); - public virtual List GetWindowList() => throw new NotImplementedException("NativeAPI.GetWindowList is not implemented."); - public virtual void HideWindow(IntPtr handle) => throw new NotImplementedException("NativeAPI.HideWindow is not implemented."); - public virtual void CopyText(string text) => throw new NotImplementedException("NativeAPI.CopyText is not implemented."); - public virtual void CopyImage(Image image) => CopyImage(image, "image.png"); // this could will never run - - public virtual void CopyImage(Image image, string? fileName) => throw new NotImplementedException("NativeAPI.CopyImage is not implemented."); - public virtual Rectangle GetWindowRectangle(WindowInfo window) => throw new NotImplementedException("NativeAPI.GetWindowRect is not implemented."); - public virtual Rectangle GetWindowRectangle(IntPtr windowHandle) => throw new NotImplementedException("NativeAPI.GetWindowRect is not implemented."); - public virtual Point GetCursorPosition() => throw new NotImplementedException("NativeAPI.GetCursorPosition is not implemented."); - public virtual Screen? GetScreen(Point pos) => - throw new NotImplementedException("NativeAPI.GetScreen is not implemented"); -} diff --git a/SnapX.Core/Utils/Native/WindowsAPI.cs b/SnapX.Core/Utils/Native/WindowsAPI.cs index 783f2aaee..373e7b056 100644 --- a/SnapX.Core/Utils/Native/WindowsAPI.cs +++ b/SnapX.Core/Utils/Native/WindowsAPI.cs @@ -19,7 +19,7 @@ namespace SnapX.Core.Utils.Native; // Windows 10 version 1903 [SupportedOSPlatform("windows10.0.18362")] -public class WindowsAPI : NativeAPI +public class WindowsAPI : INativeAPI { // Constants for allocating memory and setting data format public const uint CF_TEXT = 1; diff --git a/SnapX.Core/Utils/Native/X11ClipboardHandler.cs b/SnapX.Core/Utils/Native/X11ClipboardHandler.cs index a08e4ea6f..505b2d0e1 100644 --- a/SnapX.Core/Utils/Native/X11ClipboardHandler.cs +++ b/SnapX.Core/Utils/Native/X11ClipboardHandler.cs @@ -2,14 +2,14 @@ using System.Text; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Formats.Png; +using SnapX.Core.Interfaces; namespace SnapX.Core.Utils.Native; public class X11ClipboardHandler : IDisposable { - private static X11ClipboardHandler? _instance; private static readonly Lock _lock = new(); - + private readonly ILoggerService Logger; private IntPtr _display; private IntPtr _clipboardWindow; private Thread? _eventThread; @@ -25,16 +25,16 @@ public class X11ClipboardHandler : IDisposable private Image? _currentImage; private string? _currentFilename; - private X11ClipboardHandler() + public X11ClipboardHandler(ILoggerService Logger) { _display = LinuxAPI.XOpenDisplay(null); if (_display == IntPtr.Zero) { - throw new Exception("Unable to open X11 display for clipboard handler."); + throw new Exception("Unable to open X11 display for clipboard handler"); } - _clipboardWindow = LinuxAPI.XCreateSimpleWindow(_display, LinuxAPI.XDefaultRootWindow(_display), - 0, 0, 1, 1, 0, 0, 0); + _clipboardWindow = LinuxAPI.XCreateSimpleWindow(_display, LinuxAPI.XDefaultRootWindow(_display), 0, 0, 1, 1, 0, 0, 0); + this.Logger = Logger; LinuxAPI.XSelectInput(_display, _clipboardWindow, LinuxAPI.SelectionClearMask | LinuxAPI.SelectionRequestMask); @@ -48,19 +48,7 @@ private X11ClipboardHandler() }; _eventThread.Start(); - DebugHelper.Logger?.Debug("X11ClipboardHandler initialized and event loop started."); - } - - public static X11ClipboardHandler Instance - { - get - { - lock (_lock) - { - _instance ??= new X11ClipboardHandler(); - return _instance; - } - } + Logger.Debug("X11ClipboardHandler initialized and event loop started"); } private void InitializeAtoms() @@ -85,11 +73,11 @@ public void SetImage(Image image, string? filename = null) var owner = LinuxAPI.XGetSelectionOwner(_display, _atomClipboard); if (owner == _clipboardWindow) { - DebugHelper.Logger?.Debug($"Successfully claimed X11 CLIPBOARD ownership for image and filename '{_currentFilename}'."); + Logger.Debug("Successfully claimed X11 CLIPBOARD ownership for image and filename \'{CurrentFilename}\'", _currentFilename); } else { - DebugHelper.Logger?.Warning("Failed to claim X11 CLIPBOARD ownership. Another application might be the owner."); + Logger.Warning("Failed to claim X11 CLIPBOARD ownership. Another application might be the owner"); } } } @@ -114,16 +102,14 @@ private void EventLoop(CancellationToken cancellationToken) case LinuxAPI.SelectionClear: HandleSelectionClear(eventData.xselectionclear); break; - default: - break; } } - DebugHelper.Logger?.Debug("X11ClipboardHandler event loop terminated."); + Logger.Debug("X11ClipboardHandler event loop terminated"); } private void HandleSelectionRequest(LinuxAPI.XSelectionRequestEvent request) { - DebugHelper.Logger?.Debug($"SelectionRequest received: Target {GetAtomName(request.target)}"); + Logger.Debug("SelectionRequest received: Target {AtomName}", GetAtomName(request.target)); var property = request.property; var type = IntPtr.Zero; @@ -135,20 +121,20 @@ private void HandleSelectionRequest(LinuxAPI.XSelectionRequestEvent request) { if (request.selection != _atomClipboard) { - DebugHelper.Logger?.Debug("Selection request for non-CLIPBOARD selection ignored."); + Logger.Debug("Selection request for non-CLIPBOARD selection ignored"); return; } if (_currentImage == null) { - DebugHelper.Logger?.Warning("Selection request received but no image is set."); + Logger.Warning("Selection request received but no image is set"); property = IntPtr.Zero; type = IntPtr.Zero; } else if (request.target == _atomTargets) { - DebugHelper.Logger?.Debug("Responding to TARGETS request."); - IntPtr[] supportedTargets = { _atomTargets, _atomPng, _atomImagePng, _atomUtf8String }; + Logger.Debug("Responding to TARGETS request"); + IntPtr[] supportedTargets = [_atomTargets, _atomPng, _atomImagePng, _atomUtf8String]; data = new byte[supportedTargets.Length * Marshal.SizeOf()]; for (int i = 0; i < supportedTargets.Length; i++) { @@ -160,7 +146,7 @@ private void HandleSelectionRequest(LinuxAPI.XSelectionRequestEvent request) } else if (request.target == _atomPng || request.target == _atomImagePng) { - DebugHelper.Logger?.Debug($"Responding to image/png request. Image dimensions: {_currentImage.Width}x{_currentImage.Height}"); + Logger.Debug("Responding to image/png request. Image dimensions: {Width}x{Height}", _currentImage.Width, _currentImage.Height); using var ms = new MemoryStream(); _currentImage.Save(ms, new PngEncoder()); data = ms.ToArray(); @@ -170,7 +156,7 @@ private void HandleSelectionRequest(LinuxAPI.XSelectionRequestEvent request) } else if (request.target == _atomUtf8String && !string.IsNullOrEmpty(_currentFilename)) { - DebugHelper.Logger?.Debug("Responding to UTF8_STRING request (filename)."); + Logger.Debug("Responding to UTF8_STRING request (filename)"); data = Encoding.UTF8.GetBytes(_currentFilename); type = _atomUtf8String; format = 8; @@ -178,7 +164,7 @@ private void HandleSelectionRequest(LinuxAPI.XSelectionRequestEvent request) } else { - DebugHelper.Logger?.Debug($"Unsupported selection target: {GetAtomName(request.target)}."); + Logger.Debug("Unsupported selection target: {AtomName}", GetAtomName(request.target)); property = IntPtr.Zero; type = IntPtr.Zero; } @@ -186,17 +172,17 @@ private void HandleSelectionRequest(LinuxAPI.XSelectionRequestEvent request) if (property != IntPtr.Zero && data != null) { LinuxAPI.XChangeProperty(_display, request.requestor, property, type, format, LinuxAPI.PropModeReplace, data, nElements); - DebugHelper.Logger?.Debug($"XChangeProperty successful for target {GetAtomName(request.target)}."); + Logger.Debug("XChangeProperty successful for target {AtomName}", GetAtomName(request.target)); } else if (property != IntPtr.Zero && data == null) { - DebugHelper.Logger?.Debug($"No data to provide for target {GetAtomName(request.target)}, setting property to None."); + Logger.Debug("No data to provide for target {AtomName}, setting property to None", GetAtomName(request.target)); property = IntPtr.Zero; } } catch (Exception ex) { - DebugHelper.Logger?.Error($"Error handling SelectionRequest: {ex.Message}"); + Logger.Error("Error handling SelectionRequest: {ExMessage}", ex.Message); property = IntPtr.Zero; } finally @@ -231,11 +217,11 @@ private void SendSelectionNotify(IntPtr requestor, IntPtr selection, IntPtr targ if (status == 0) { - DebugHelper.Logger?.Warning("XSendEvent for SelectionNotify failed."); + Logger.Warning("XSendEvent for SelectionNotify failed"); } else { - DebugHelper.Logger?.Debug($"SelectionNotify sent to {requestor} (property: {GetAtomName(property)})."); + Logger.Debug("SelectionNotify sent to {Requestor} (property: {AtomName})", requestor, GetAtomName(property)); } } finally @@ -248,7 +234,7 @@ private void HandleSelectionClear(LinuxAPI.XSelectionClearEvent clear) { if (clear.selection == _atomClipboard) { - DebugHelper.Logger?.Debug("CLIPBOARD ownership lost (SelectionClear event)."); + Logger.Debug("CLIPBOARD ownership lost (SelectionClear event)"); lock (_lock) { _currentImage = null; @@ -269,7 +255,7 @@ private string GetAtomName(IntPtr atom) public void Dispose() { - DebugHelper.Logger?.Debug("Disposing X11ClipboardHandler."); + Logger.Debug("Disposing X11ClipboardHandler"); _cts.Cancel(); _eventThread?.Join(); @@ -278,11 +264,9 @@ public void Dispose() LinuxAPI.XDestroyWindow(_display, _clipboardWindow); _clipboardWindow = IntPtr.Zero; } - if (_display != IntPtr.Zero) - { - LinuxAPI.XCloseDisplay(_display); - _display = IntPtr.Zero; - } - _instance = null; + + if (_display == IntPtr.Zero) return; + LinuxAPI.XCloseDisplay(_display); + _display = IntPtr.Zero; } } diff --git a/SnapX.Core/VersionEnforcer.cs b/SnapX.Core/VersionEnforcer.cs index 411b6f5c1..aa0f7b17f 100644 --- a/SnapX.Core/VersionEnforcer.cs +++ b/SnapX.Core/VersionEnforcer.cs @@ -3,43 +3,45 @@ using System.Text; using System.Text.Json; using System.Text.Json.Serialization; +using SnapX.Core.Interfaces; namespace SnapX.Core; -// I might've lost my marbles working on this class. -// Sorry for the bad code, but, it works! - [JsonSerializable(typeof(VersionEnforcer.LockFileContent))] internal sealed partial class VersionEnforcerContext : JsonSerializerContext; public sealed class VersionEnforcer : IDisposable { + private ILoggerService _logger; private readonly string _lockFilePath; private FileStream? _lockFileStream; private readonly string _currentVersion; private readonly int _currentPID; private readonly bool _startupFailed; private bool _ownsLockFile; + internal record LockFileContent { - public int ProcessId { get; set; } - public string Version { get; set; } + public required int ProcessId { get; set; } + public required string Version { get; set; } } - public VersionEnforcer(string lockDirectory) + public VersionEnforcer(string lockDirectory, ILoggerService logger) { if (string.IsNullOrWhiteSpace(lockDirectory)) { - throw new ArgumentException("Lock directory cannot be null or empty.", nameof(lockDirectory)); + throw new ArgumentException($"Lock directory cannot be null or empty {nameof(lockDirectory)}"); } + _logger = logger; + try { Directory.CreateDirectory(lockDirectory); } catch (Exception ex) { - DebugHelper.WriteLine($"VersionEnforcer failed to create lock directory '{lockDirectory}' . Skipping version lock checks. Good luck."); - DebugHelper.WriteException(ex); + _logger.Information("VersionEnforcer failed to create lock directory \'{LockDirectory}\' . Skipping version lock checks. Good luck", lockDirectory); + _logger.Error(ex.ToString()); _startupFailed = true; } @@ -135,7 +137,7 @@ private void HandleExistingVersion(LockFileContent? lockFileInfo, string existin var statement = !isPreviousInstanceRunning ? $"Took ownership from previous dead instance (same version, PID: {previousInstance})" : $"An existing instance (same version, PID: {lockFileInfo?.ProcessId}) was detected. This is supported. :)"; - DebugHelper.WriteLine($"Application (Version: {_currentVersion}) started. {statement}"); + _logger.Information("Application (Version: {CurrentVersion}) started. {Statement}", _currentVersion, statement); } private void HandleNoExistingVersion(ref LockFileContent? lockFileInfo) @@ -147,14 +149,12 @@ private void HandleNoExistingVersion(ref LockFileContent? lockFileInfo) }; _ownsLockFile = true; WriteVersionInfoToLockFile(lockFileInfo); - DebugHelper.WriteLine( - $"Application (Version: {_currentVersion}) started. First instance of this version (or lock file was empty)."); + _logger.Information("Application (Version: {CurrentVersion}) started. First instance of this version (or lock file was empty)", _currentVersion); } private void HandleLockFileInUse() { - DebugHelper.WriteLine( - $"Application (Version: {_currentVersion}) detected another instance running which holds the lock. This instance will try to read its version."); + _logger.Information("Application (Version: {CurrentVersion}) detected another instance running which holds the lock. This instance will try to read its version", _currentVersion); try { @@ -187,8 +187,7 @@ private void HandleLockFileInUse() } if (lockFileInfo?.ProcessId == _currentPID) _ownsLockFile = true; - DebugHelper.WriteLine( - $"Application Lock (Version: {_currentVersion}) is compatible with the running instance (same version). Running alongside."); + _logger.Information("Application Lock (Version: {CurrentVersion}) is compatible with the running instance (same version). Running alongside", _currentVersion); } catch (Exception innerEx) { @@ -221,7 +220,7 @@ private void HandleLockFileInUse() } catch (Exception ex) { - DebugHelper.WriteLine($"VersionLock failed to parse/deserialize LockFile at {_lockFilePath}. Nuking file from orbit."); + _logger.Information("VersionLock failed to parse/deserialize LockFile at {LockFilePath}. Nuking file from orbit", _lockFilePath); DebugHelper.WriteException(ex); try { @@ -260,7 +259,7 @@ private static bool IsProcessRunning(int pid) } catch (InvalidOperationException) { - // Process has exited (may occur if HasExited was not yet updated). + // The process has exited (may occur if HasExited was not yet updated). return false; } catch (Exception) @@ -274,7 +273,7 @@ private void WriteVersionInfoToLockFile(LockFileContent versionInfo) { if (_lockFileStream == null) { - DebugHelper.WriteLine($"VersionEnforcer.WriteVersionInfoToLockFile() called when _lockFileStream is null. Redefining."); + _logger.Information($"VersionEnforcer.WriteVersionInfoToLockFile() called when _lockFileStream is null. Redefining."); _lockFileStream = new FileStream( _lockFilePath, FileMode.OpenOrCreate, @@ -302,9 +301,10 @@ public void Dispose() { if (_lockFileStream == null) { - DebugHelper.WriteLine(_ownsLockFile - ? $"VersionEnforcer owns the lock file at {_lockFilePath} yet _lockFileStream is null! BUG!" - : $"VersionLock _lockFileStream is null! Lockfile at {_lockFilePath} "); + _logger.Information(_ownsLockFile + ? string.Format($"VersionEnforcer owns the lock file at {{0}} yet {nameof(_lockFileStream)} is null! BUG!", + _lockFilePath) + : string.Format($"VersionLock {nameof(_lockFileStream)} is null! Lockfile at {{0}} ", _lockFilePath)); } var lockfileInfo = ReadLockFileContent(); if (lockfileInfo is not null && !IsProcessRunning(lockfileInfo.ProcessId)) _ownsLockFile = true; @@ -317,13 +317,12 @@ public void Dispose() } catch (Exception ex) { - DebugHelper.WriteLine($"VersionLock failed to delete lockfile {_lockFilePath} while disposing."); - DebugHelper.WriteException(ex); + _logger.Error(ex, "VersionLock failed to delete lockfile {LockFilePath} while disposing", _lockFilePath); } } else { - DebugHelper.WriteLine($"VersionEnforcer does not own lockfile {_lockFilePath}. Leaving it be."); + _logger.Information("VersionEnforcer does not own lockfile {LockFilePath}. Leaving it be", _lockFilePath); } _lockFileStream?.Dispose(); _lockFileStream = null; diff --git a/SnapX.Core/Watch/WatchFolder.cs b/SnapX.Core/Watch/WatchFolder.cs index f26ce4493..9c1e541f6 100644 --- a/SnapX.Core/Watch/WatchFolder.cs +++ b/SnapX.Core/Watch/WatchFolder.cs @@ -11,7 +11,7 @@ namespace SnapX.Core.Watch; public class WatchFolder : IDisposable { public WatchFolderSettings Settings { get; set; } - public TaskSettings TaskSettings { get; set; } + public TaskSettings? TaskSettings { get; set; } public delegate void FileWatcherTriggerEventHandler(string? path); diff --git a/SnapX.Core/Watch/WatchFolderManager.cs b/SnapX.Core/Watch/WatchFolderManager.cs index d3942e982..c613e247c 100644 --- a/SnapX.Core/Watch/WatchFolderManager.cs +++ b/SnapX.Core/Watch/WatchFolderManager.cs @@ -46,7 +46,7 @@ private bool IsExist(WatchFolderSettings watchFolderSetting) return FindWatchFolder(watchFolderSetting) != null; } - public void AddWatchFolder(WatchFolderSettings watchFolderSetting, TaskSettings taskSettings) + public void AddWatchFolder(WatchFolderSettings watchFolderSetting, TaskSettings? taskSettings) { if (!IsExist(watchFolderSetting)) { diff --git a/SnapX.Core/XML/org.freedesktop.DBus.xml b/SnapX.Core/XML/org.freedesktop.DBus.xml new file mode 100644 index 000000000..3f2b33864 --- /dev/null +++ b/SnapX.Core/XML/org.freedesktop.DBus.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SnapX.Core/XML/org.kde.KWin.ScreenShot2.xml b/SnapX.Core/XML/org.kde.KWin.ScreenShot2.xml new file mode 100644 index 000000000..bc4eb4039 --- /dev/null +++ b/SnapX.Core/XML/org.kde.KWin.ScreenShot2.xml @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SnapX.Core/wayland.xml b/SnapX.Core/XML/wayland.xml similarity index 100% rename from SnapX.Core/wayland.xml rename to SnapX.Core/XML/wayland.xml diff --git a/SnapX.NativeMessagingHost/Program.cs b/SnapX.NativeMessagingHost/Program.cs index f4495d83f..dd3b84773 100644 --- a/SnapX.NativeMessagingHost/Program.cs +++ b/SnapX.NativeMessagingHost/Program.cs @@ -7,7 +7,7 @@ if (args.Length == 0) { - Console.WriteLine("This executable is used to receive data from a browser addon and send it to SnapX."); + Console.WriteLine(@"This executable is used to receive data from a browser addon and send it to SnapX."); return; } diff --git a/SnapX.NativeMessagingHost/SnapX.NativeMessagingHost.csproj b/SnapX.NativeMessagingHost/SnapX.NativeMessagingHost.csproj index 7a7743e09..401e124b4 100644 --- a/SnapX.NativeMessagingHost/SnapX.NativeMessagingHost.csproj +++ b/SnapX.NativeMessagingHost/SnapX.NativeMessagingHost.csproj @@ -2,6 +2,7 @@ Exe SnapX_NativeMessagingHost + SnapX.NativeMessagingHost.Tests SnapX NativeMessagingHost none false diff --git a/SnapX.sln b/SnapX.sln index a21af2f2d..9396cf703 100644 --- a/SnapX.sln +++ b/SnapX.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.0.32112.339 @@ -21,62 +21,105 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SnapX.NativeMessagingHost", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "build", "build\build.csproj", "{96432C2D-0F1D-4B69-97CB-9F54C1873C1E}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0AB3BF05-4346-4AA6-1389-037BE0695223}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Build.Tests", "tests\Build.Tests\Build.Tests.csproj", "{3783A9EF-B03E-48C3-9EF8-91A9E40372B4}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {96432C2D-0F1D-4B69-97CB-9F54C1873C1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {96432C2D-0F1D-4B69-97CB-9F54C1873C1E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C5AE4585-E9EC-4FA3-B75A-E1210635ACB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C5AE4585-E9EC-4FA3-B75A-E1210635ACB6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C5AE4585-E9EC-4FA3-B75A-E1210635ACB6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C5AE4585-E9EC-4FA3-B75A-E1210635ACB6}.Release|Any CPU.Build.0 = Release|Any CPU - {E7DE6237-AEA2-498B-8F56-9B392472C490}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E7DE6237-AEA2-498B-8F56-9B392472C490}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E7DE6237-AEA2-498B-8F56-9B392472C490}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E7DE6237-AEA2-498B-8F56-9B392472C490}.Release|Any CPU.Build.0 = Release|Any CPU - {DBDB0DAA-B3AE-4CC4-A8C2-20550B7F32E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DBDB0DAA-B3AE-4CC4-A8C2-20550B7F32E3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DBDB0DAA-B3AE-4CC4-A8C2-20550B7F32E3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DBDB0DAA-B3AE-4CC4-A8C2-20550B7F32E3}.Release|Any CPU.Build.0 = Release|Any CPU - {E1C94415-3424-4517-A2A1-B2FDD1F59C67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E1C94415-3424-4517-A2A1-B2FDD1F59C67}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E1C94415-3424-4517-A2A1-B2FDD1F59C67}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E1C94415-3424-4517-A2A1-B2FDD1F59C67}.Release|Any CPU.Build.0 = Release|Any CPU - {750C6F46-2C5A-4488-81D3-3B35CA50F3EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {750C6F46-2C5A-4488-81D3-3B35CA50F3EE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {750C6F46-2C5A-4488-81D3-3B35CA50F3EE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {750C6F46-2C5A-4488-81D3-3B35CA50F3EE}.Release|Any CPU.Build.0 = Release|Any CPU - {D13441B6-96E1-4D1B-8A95-58A7D6CB1E24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D13441B6-96E1-4D1B-8A95-58A7D6CB1E24}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D13441B6-96E1-4D1B-8A95-58A7D6CB1E24}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D13441B6-96E1-4D1B-8A95-58A7D6CB1E24}.Release|Any CPU.Build.0 = Release|Any CPU - {1A190E53-1419-4CC2-B0E5-3BC7EA861C8B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1A190E53-1419-4CC2-B0E5-3BC7EA861C8B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1A190E53-1419-4CC2-B0E5-3BC7EA861C8B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1A190E53-1419-4CC2-B0E5-3BC7EA861C8B}.Release|Any CPU.Build.0 = Release|Any CPU - {3AAB8CC5-156D-4738-93D3-625BAA9D2ABD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3AAB8CC5-156D-4738-93D3-625BAA9D2ABD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3AAB8CC5-156D-4738-93D3-625BAA9D2ABD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3AAB8CC5-156D-4738-93D3-625BAA9D2ABD}.Release|Any CPU.Build.0 = Release|Any CPU + {9C0D2877-B8F3-4D84-BD4C-E89173EBDD96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9C0D2877-B8F3-4D84-BD4C-E89173EBDD96}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9C0D2877-B8F3-4D84-BD4C-E89173EBDD96}.Debug|x64.ActiveCfg = Debug|Any CPU + {9C0D2877-B8F3-4D84-BD4C-E89173EBDD96}.Debug|x64.Build.0 = Debug|Any CPU + {9C0D2877-B8F3-4D84-BD4C-E89173EBDD96}.Debug|x86.ActiveCfg = Debug|Any CPU + {9C0D2877-B8F3-4D84-BD4C-E89173EBDD96}.Debug|x86.Build.0 = Debug|Any CPU + {9C0D2877-B8F3-4D84-BD4C-E89173EBDD96}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9C0D2877-B8F3-4D84-BD4C-E89173EBDD96}.Release|Any CPU.Build.0 = Release|Any CPU + {9C0D2877-B8F3-4D84-BD4C-E89173EBDD96}.Release|x64.ActiveCfg = Release|Any CPU + {9C0D2877-B8F3-4D84-BD4C-E89173EBDD96}.Release|x64.Build.0 = Release|Any CPU + {9C0D2877-B8F3-4D84-BD4C-E89173EBDD96}.Release|x86.ActiveCfg = Release|Any CPU + {9C0D2877-B8F3-4D84-BD4C-E89173EBDD96}.Release|x86.Build.0 = Release|Any CPU {74428450-9146-4434-B34F-D9D3213D7B0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {74428450-9146-4434-B34F-D9D3213D7B0E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {74428450-9146-4434-B34F-D9D3213D7B0E}.Debug|x64.ActiveCfg = Debug|Any CPU + {74428450-9146-4434-B34F-D9D3213D7B0E}.Debug|x64.Build.0 = Debug|Any CPU + {74428450-9146-4434-B34F-D9D3213D7B0E}.Debug|x86.ActiveCfg = Debug|Any CPU + {74428450-9146-4434-B34F-D9D3213D7B0E}.Debug|x86.Build.0 = Debug|Any CPU {74428450-9146-4434-B34F-D9D3213D7B0E}.Release|Any CPU.ActiveCfg = Release|Any CPU {74428450-9146-4434-B34F-D9D3213D7B0E}.Release|Any CPU.Build.0 = Release|Any CPU + {74428450-9146-4434-B34F-D9D3213D7B0E}.Release|x64.ActiveCfg = Release|Any CPU + {74428450-9146-4434-B34F-D9D3213D7B0E}.Release|x64.Build.0 = Release|Any CPU + {74428450-9146-4434-B34F-D9D3213D7B0E}.Release|x86.ActiveCfg = Release|Any CPU + {74428450-9146-4434-B34F-D9D3213D7B0E}.Release|x86.Build.0 = Release|Any CPU {89525D3B-F639-4C0B-8CFF-F55A0C52D344}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {89525D3B-F639-4C0B-8CFF-F55A0C52D344}.Debug|Any CPU.Build.0 = Debug|Any CPU + {89525D3B-F639-4C0B-8CFF-F55A0C52D344}.Debug|x64.ActiveCfg = Debug|Any CPU + {89525D3B-F639-4C0B-8CFF-F55A0C52D344}.Debug|x64.Build.0 = Debug|Any CPU + {89525D3B-F639-4C0B-8CFF-F55A0C52D344}.Debug|x86.ActiveCfg = Debug|Any CPU + {89525D3B-F639-4C0B-8CFF-F55A0C52D344}.Debug|x86.Build.0 = Debug|Any CPU {89525D3B-F639-4C0B-8CFF-F55A0C52D344}.Release|Any CPU.ActiveCfg = Release|Any CPU {89525D3B-F639-4C0B-8CFF-F55A0C52D344}.Release|Any CPU.Build.0 = Release|Any CPU - {9C0D2877-B8F3-4D84-BD4C-E89173EBDD96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9C0D2877-B8F3-4D84-BD4C-E89173EBDD96}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9C0D2877-B8F3-4D84-BD4C-E89173EBDD96}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9C0D2877-B8F3-4D84-BD4C-E89173EBDD96}.Release|Any CPU.Build.0 = Release|Any CPU + {89525D3B-F639-4C0B-8CFF-F55A0C52D344}.Release|x64.ActiveCfg = Release|Any CPU + {89525D3B-F639-4C0B-8CFF-F55A0C52D344}.Release|x64.Build.0 = Release|Any CPU + {89525D3B-F639-4C0B-8CFF-F55A0C52D344}.Release|x86.ActiveCfg = Release|Any CPU + {89525D3B-F639-4C0B-8CFF-F55A0C52D344}.Release|x86.Build.0 = Release|Any CPU + {3AAB8CC5-156D-4738-93D3-625BAA9D2ABD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3AAB8CC5-156D-4738-93D3-625BAA9D2ABD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3AAB8CC5-156D-4738-93D3-625BAA9D2ABD}.Debug|x64.ActiveCfg = Debug|Any CPU + {3AAB8CC5-156D-4738-93D3-625BAA9D2ABD}.Debug|x64.Build.0 = Debug|Any CPU + {3AAB8CC5-156D-4738-93D3-625BAA9D2ABD}.Debug|x86.ActiveCfg = Debug|Any CPU + {3AAB8CC5-156D-4738-93D3-625BAA9D2ABD}.Debug|x86.Build.0 = Debug|Any CPU + {3AAB8CC5-156D-4738-93D3-625BAA9D2ABD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3AAB8CC5-156D-4738-93D3-625BAA9D2ABD}.Release|Any CPU.Build.0 = Release|Any CPU + {3AAB8CC5-156D-4738-93D3-625BAA9D2ABD}.Release|x64.ActiveCfg = Release|Any CPU + {3AAB8CC5-156D-4738-93D3-625BAA9D2ABD}.Release|x64.Build.0 = Release|Any CPU + {3AAB8CC5-156D-4738-93D3-625BAA9D2ABD}.Release|x86.ActiveCfg = Release|Any CPU + {3AAB8CC5-156D-4738-93D3-625BAA9D2ABD}.Release|x86.Build.0 = Release|Any CPU + {254E398D-F7F5-4B2A-9024-5C121EA6C564}.Debug|x64.ActiveCfg = Debug|Any CPU + {254E398D-F7F5-4B2A-9024-5C121EA6C564}.Debug|x64.Build.0 = Debug|Any CPU + {254E398D-F7F5-4B2A-9024-5C121EA6C564}.Debug|x86.ActiveCfg = Debug|Any CPU + {254E398D-F7F5-4B2A-9024-5C121EA6C564}.Debug|x86.Build.0 = Debug|Any CPU + {254E398D-F7F5-4B2A-9024-5C121EA6C564}.Release|x64.ActiveCfg = Release|Any CPU + {254E398D-F7F5-4B2A-9024-5C121EA6C564}.Release|x64.Build.0 = Release|Any CPU + {254E398D-F7F5-4B2A-9024-5C121EA6C564}.Release|x86.ActiveCfg = Release|Any CPU + {254E398D-F7F5-4B2A-9024-5C121EA6C564}.Release|x86.Build.0 = Release|Any CPU + {96432C2D-0F1D-4B69-97CB-9F54C1873C1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {96432C2D-0F1D-4B69-97CB-9F54C1873C1E}.Debug|x64.ActiveCfg = Debug|Any CPU + {96432C2D-0F1D-4B69-97CB-9F54C1873C1E}.Debug|x64.Build.0 = Debug|Any CPU + {96432C2D-0F1D-4B69-97CB-9F54C1873C1E}.Debug|x86.ActiveCfg = Debug|Any CPU + {96432C2D-0F1D-4B69-97CB-9F54C1873C1E}.Debug|x86.Build.0 = Debug|Any CPU + {96432C2D-0F1D-4B69-97CB-9F54C1873C1E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {96432C2D-0F1D-4B69-97CB-9F54C1873C1E}.Release|x64.ActiveCfg = Release|Any CPU + {96432C2D-0F1D-4B69-97CB-9F54C1873C1E}.Release|x64.Build.0 = Release|Any CPU + {96432C2D-0F1D-4B69-97CB-9F54C1873C1E}.Release|x86.ActiveCfg = Release|Any CPU + {96432C2D-0F1D-4B69-97CB-9F54C1873C1E}.Release|x86.Build.0 = Release|Any CPU + {3783A9EF-B03E-48C3-9EF8-91A9E40372B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3783A9EF-B03E-48C3-9EF8-91A9E40372B4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3783A9EF-B03E-48C3-9EF8-91A9E40372B4}.Debug|x64.ActiveCfg = Debug|Any CPU + {3783A9EF-B03E-48C3-9EF8-91A9E40372B4}.Debug|x64.Build.0 = Debug|Any CPU + {3783A9EF-B03E-48C3-9EF8-91A9E40372B4}.Debug|x86.ActiveCfg = Debug|Any CPU + {3783A9EF-B03E-48C3-9EF8-91A9E40372B4}.Debug|x86.Build.0 = Debug|Any CPU + {3783A9EF-B03E-48C3-9EF8-91A9E40372B4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3783A9EF-B03E-48C3-9EF8-91A9E40372B4}.Release|Any CPU.Build.0 = Release|Any CPU + {3783A9EF-B03E-48C3-9EF8-91A9E40372B4}.Release|x64.ActiveCfg = Release|Any CPU + {3783A9EF-B03E-48C3-9EF8-91A9E40372B4}.Release|x64.Build.0 = Release|Any CPU + {3783A9EF-B03E-48C3-9EF8-91A9E40372B4}.Release|x86.ActiveCfg = Release|Any CPU + {3783A9EF-B03E-48C3-9EF8-91A9E40372B4}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {3783A9EF-B03E-48C3-9EF8-91A9E40372B4} = {0AB3BF05-4346-4AA6-1389-037BE0695223} + EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DEACF1C2-28EE-44DF-B55E-2234F6137272} EndGlobalSection diff --git a/SnapX.slnx b/SnapX.slnx index 364873989..7272b6be3 100644 --- a/SnapX.slnx +++ b/SnapX.slnx @@ -4,11 +4,12 @@ - + - + + \ No newline at end of file diff --git a/global.json b/global.json index 6ea54577f..f477575a2 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "9.0.107", + "version": "9.0.108", "rollForward": "latestMajor", "allowPrerelease": true } diff --git a/packaging/snapx.spec b/packaging/snapx.spec index 8268cc13c..1d097b015 100644 --- a/packaging/snapx.spec +++ b/packaging/snapx.spec @@ -31,7 +31,11 @@ Name: snapx Version: %{version} +%if 0%{?fedora} +Release: %autorelease +%else Release: 1%{?dist} +%endif Summary: Screenshot tool that handles images, text, and video. License: GPL-3.0-or-later From e5770b0c1fece2ffd9136c8914404b46e8577502 Mon Sep 17 00:00:00 2001 From: Brycen G Date: Sat, 12 Jul 2025 11:25:36 -0400 Subject: [PATCH 13/31] ci(build): only remove Android & Haskell for space on Ubuntu 24.04 Debug runner --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 370aab843..e0d03ef0f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -52,9 +52,9 @@ jobs: android: true dotnet: false haskell: true - large-packages: true - docker-images: true - swap-storage: true + large-packages: false + docker-images: false + swap-storage: false - name: Setup dotnet uses: actions/setup-dotnet@v4 with: From 2e12a111950d703e330db407bda99e2c51eef83f Mon Sep 17 00:00:00 2001 From: Brycen G Date: Sat, 12 Jul 2025 13:03:23 -0400 Subject: [PATCH 14/31] chore(Core): bring Windows API up to speed --- .../SharpCapture/Windows/WindowsCapture.cs | 9 +++-- SnapX.Core/Utils/Native/WindowsAPI.cs | 40 +++++++++++++++---- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/SnapX.Core/SharpCapture/Windows/WindowsCapture.cs b/SnapX.Core/SharpCapture/Windows/WindowsCapture.cs index 51d604628..465ae366f 100644 --- a/SnapX.Core/SharpCapture/Windows/WindowsCapture.cs +++ b/SnapX.Core/SharpCapture/Windows/WindowsCapture.cs @@ -10,13 +10,14 @@ using Vortice.Direct3D11; using Vortice.DXGI; using Windows.Win32; +using SnapX.Core.Job; using WinRT; namespace SnapX.Core.SharpCapture.Windows; [SupportedOSPlatform("windows10.0.19045")] -public class WindowsCapture : BaseCapture +public class WindowsCapture : BaseSharpCapture { private bool IsSupportedFeatureLevel(IDXGIAdapter1 adapter, FeatureLevel featureLevel, DeviceCreationFlags creationFlags) @@ -40,7 +41,7 @@ private bool IsSupportedFeatureLevel(IDXGIAdapter1 adapter, FeatureLevel feature return false; } - public override async Task CaptureFullscreen() + public override async Task CaptureFullscreen(TaskSettings? taskSettings = null) { var factory = DXGI.CreateDXGIFactory1()!; @@ -103,7 +104,7 @@ private bool IsSupportedFeatureLevel(IDXGIAdapter1 adapter, FeatureLevel feature } - public override async Task CaptureScreen(Point? pos) + public override async Task CaptureScreen(Point? pos, TaskSettings? taskSettings = null) { var factory = DXGI.CreateDXGIFactory1()!; @@ -184,7 +185,7 @@ private static ID3D11Texture2D Texture2DFromSurface(IDirect3DSurface surface) var texture = access.QueryInterface(); return texture; } - public override async Task CaptureWindow(Point pos) + public override async Task CaptureWindow(Point pos, TaskSettings? taskSettings = null) { if (!GraphicsCaptureSession.IsSupported()) { diff --git a/SnapX.Core/Utils/Native/WindowsAPI.cs b/SnapX.Core/Utils/Native/WindowsAPI.cs index 373e7b056..bf4471c59 100644 --- a/SnapX.Core/Utils/Native/WindowsAPI.cs +++ b/SnapX.Core/Utils/Native/WindowsAPI.cs @@ -26,7 +26,7 @@ public class WindowsAPI : INativeAPI private const uint CF_DIB = 8; private const uint CF_HDROP = 15; - public override void ShowWindow(WindowInfo Window) + public void ShowWindow(WindowInfo Window) { var handle = Window.Handle; if (handle == IntPtr.Zero) @@ -37,7 +37,7 @@ public override void ShowWindow(WindowInfo Window) PInvoke.ShowWindow(new HWND(handle), SHOW_WINDOW_CMD.SW_SHOW); } - public override void ShowWindow(IntPtr hwnd) + public void ShowWindow(IntPtr hwnd) { if (hwnd == IntPtr.Zero) { @@ -47,6 +47,21 @@ public override void ShowWindow(IntPtr hwnd) PInvoke.ShowWindow(new HWND(hwnd), SHOW_WINDOW_CMD.SW_SHOW); } + public Image GetJumboFileIcon(string filePath, bool jumboSize = true) + { + throw new NotImplementedException(); + } + + public void HideWindow(WindowInfo windowInfo) + { + throw new NotImplementedException(); + } + + public void HideWindow(IntPtr handle) + { + throw new NotImplementedException(); + } + // Method to check if a window is minimized public static bool IsWindowMinimized(IntPtr hwnd) { @@ -99,7 +114,7 @@ private static BOOL EnumWindowsCallback(HWND hwnd, LPARAM lParam) private static List windowList = []; - public override List GetWindowList() + public List GetWindowList() { windowList.Clear(); unsafe @@ -114,7 +129,7 @@ public override List GetWindowList() return windowList; } - public override void CopyText(string text) + public void CopyText(string text) { if (!PInvoke.OpenClipboard(new HWND())) { @@ -142,12 +157,23 @@ public override void CopyText(string text) } } - public override Point GetCursorPosition() + public Rectangle GetWindowRectangle(IntPtr windowHandle) + { + throw new NotImplementedException(); + } + + public Point GetCursorPosition() { PInvoke.GetCursorPos(out var LpPoint); return new Point(LpPoint.X, LpPoint.Y); } - public override void CopyImage(Image image, string? filename = null) + + public Screen? GetScreen(Point pos) + { + throw new NotImplementedException(); + } + + public void CopyImage(Image image, string? filename = null) { PInvoke.OpenClipboard(new HWND()); PInvoke.EmptyClipboard(); @@ -202,7 +228,7 @@ public override void CopyImage(Image image, string? filename = null) } } - public override Rectangle GetWindowRectangle(WindowInfo Window) + public Rectangle GetWindowRectangle(WindowInfo Window) { var handle = Window.Handle; if (handle == IntPtr.Zero) From 2f6137e9f3c197c8f404e01039d1492ef5dbb9d8 Mon Sep 17 00:00:00 2001 From: Brycen G Date: Mon, 14 Jul 2025 12:14:13 -0400 Subject: [PATCH 15/31] ci(build): do not remove Android runtime It's not needed to remove anymore, the 6.2GiB from the Haskell runtime removal should be all that's needed? --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e0d03ef0f..0866f93dd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -49,7 +49,7 @@ jobs: # all of these default to true, but feel free to set to # "false" if necessary for your workflow - android: true + android: false dotnet: false haskell: true large-packages: false From f413df4a44301235f54eb6e1d8a0284c0b1ba8c0 Mon Sep 17 00:00:00 2001 From: Brycen G Date: Mon, 14 Jul 2025 15:27:29 -0400 Subject: [PATCH 16/31] fix(Avalonia): historyItem copy on homepage sometimes failing --- SnapX.Avalonia/Views/HomePageView.axaml.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/SnapX.Avalonia/Views/HomePageView.axaml.cs b/SnapX.Avalonia/Views/HomePageView.axaml.cs index 0a12988b9..b830f717b 100644 --- a/SnapX.Avalonia/Views/HomePageView.axaml.cs +++ b/SnapX.Avalonia/Views/HomePageView.axaml.cs @@ -115,7 +115,15 @@ private void OpenFolder_Click(object? sender, RoutedEventArgs e) private void DynamicCopy(object? sender, RoutedEventArgs e) { if (sender is not MenuFlyoutItem menuItem) return; - var text = menuItem.Tag as string; - ClipboardService.Owner.Clipboard?.SetTextAsync(text); + var tag = menuItem.Tag; + if (tag is null) + { + DebugHelper.WriteLine("DynamicCopy: Tag is null"); + return; + } + var text = tag as string; + var topLevel = TopLevel.GetTopLevel(this); + var clipboard = topLevel?.Clipboard; + clipboard?.SetTextAsync(text); } } From 3ca4c345899e0e5543f8eed9ee7dbf5618f247de Mon Sep 17 00:00:00 2001 From: Brycen G Date: Wed, 16 Jul 2025 09:40:53 -0400 Subject: [PATCH 17/31] style: remove leading blank lines before SPDX license header in source files --- SnapX.Core/CLI/CLICommand.cs | 1 - SnapX.Core/CLI/CLICommandAction.cs | 1 - SnapX.Core/CLI/CLIManager.cs | 1 - SnapX.Core/CLI/ExternalCLIManager.cs | 1 - SnapX.Core/CLI/NativeMessageInput.cs | 1 - SnapX.Core/CLI/NativeMessagingHost.cs | 1 - SnapX.Core/Enums.cs | 1 - SnapX.Core/History/HistoryFilter.cs | 1 - SnapX.Core/History/HistoryItem.cs | 1 - SnapX.Core/History/HistoryItemManager.cs | 1 - SnapX.Core/History/HistoryManager.cs | 1 - SnapX.Core/History/HistorySettings.cs | 1 - SnapX.Core/Hotkey/HotkeyManager.cs | 1 - SnapX.Core/Hotkey/HotkeySettings.cs | 1 - SnapX.Core/ImageEffects/Adjustments/Alpha.cs | 1 - SnapX.Core/ImageEffects/Adjustments/BlackWhite.cs | 1 - SnapX.Core/ImageEffects/Adjustments/Brightness.cs | 1 - SnapX.Core/ImageEffects/Adjustments/Colorize.cs | 1 - SnapX.Core/ImageEffects/Adjustments/Contrast.cs | 1 - SnapX.Core/ImageEffects/Adjustments/Gamma.cs | 1 - SnapX.Core/ImageEffects/Adjustments/Grayscale.cs | 1 - SnapX.Core/ImageEffects/Adjustments/Hue.cs | 1 - SnapX.Core/ImageEffects/Adjustments/MatrixColor.cs | 1 - SnapX.Core/ImageEffects/Adjustments/ReplaceColor.cs | 1 - SnapX.Core/ImageEffects/Adjustments/Saturation.cs | 1 - SnapX.Core/ImageEffects/Adjustments/SelectiveColor.cs | 1 - SnapX.Core/ImageEffects/Adjustments/Sepia.cs | 1 - SnapX.Core/ImageEffects/Drawings/DrawBackground.cs | 1 - SnapX.Core/ImageEffects/Drawings/DrawBackgroundImage.cs | 1 - SnapX.Core/ImageEffects/Drawings/DrawBorder.cs | 1 - SnapX.Core/ImageEffects/Drawings/DrawCheckerboard.cs | 1 - SnapX.Core/ImageEffects/Drawings/DrawImage.cs | 1 - SnapX.Core/ImageEffects/Drawings/DrawParticles.cs | 1 - SnapX.Core/ImageEffects/Drawings/DrawText.cs | 1 - SnapX.Core/ImageEffects/Drawings/DrawTextEx.cs | 1 - SnapX.Core/ImageEffects/Enums.cs | 1 - SnapX.Core/ImageEffects/Filters/Blur.cs | 1 - SnapX.Core/ImageEffects/Filters/EdgeDetect.cs | 1 - SnapX.Core/ImageEffects/Filters/Emboss.cs | 1 - SnapX.Core/ImageEffects/Filters/GaussianBlur.cs | 1 - SnapX.Core/ImageEffects/Filters/Glow.cs | 1 - SnapX.Core/ImageEffects/Filters/MatrixConvolution.cs | 1 - SnapX.Core/ImageEffects/Filters/MeanRemoval.cs | 1 - SnapX.Core/ImageEffects/Filters/Outline.cs | 1 - SnapX.Core/ImageEffects/Filters/Pixelate.cs | 1 - SnapX.Core/ImageEffects/Filters/RGBSplit.cs | 1 - SnapX.Core/ImageEffects/Filters/Reflection.cs | 1 - SnapX.Core/ImageEffects/Filters/Shadow.cs | 1 - SnapX.Core/ImageEffects/Filters/Slice.cs | 1 - SnapX.Core/ImageEffects/Filters/TornEdge.cs | 1 - SnapX.Core/ImageEffects/Filters/WaveEdge.cs | 1 - SnapX.Core/ImageEffects/ImageEffect.cs | 1 - SnapX.Core/ImageEffects/ImageEffectPackager.cs | 1 - SnapX.Core/ImageEffects/ImageEffectPreset.cs | 1 - SnapX.Core/ImageEffects/Manipulations/AutoCrop.cs | 1 - SnapX.Core/ImageEffects/Manipulations/Canvas.cs | 1 - SnapX.Core/ImageEffects/Manipulations/Crop.cs | 1 - SnapX.Core/ImageEffects/Manipulations/Flip.cs | 1 - SnapX.Core/ImageEffects/Manipulations/ForceProportions.cs | 1 - SnapX.Core/ImageEffects/Manipulations/Resize.cs | 1 - SnapX.Core/ImageEffects/Manipulations/Rotate.cs | 1 - SnapX.Core/ImageEffects/Manipulations/RoundedCorners.cs | 1 - SnapX.Core/ImageEffects/Manipulations/Scale.cs | 1 - SnapX.Core/ImageEffects/Manipulations/Skew.cs | 1 - SnapX.Core/ImageEffects/WatermarkConfig.cs | 1 - SnapX.Core/Indexer/Enums.cs | 1 - SnapX.Core/Indexer/FolderInfo.cs | 1 - SnapX.Core/Indexer/HtmlHelper.cs | 1 - SnapX.Core/Indexer/Indexer.cs | 1 - SnapX.Core/Indexer/IndexerHtml.cs | 1 - SnapX.Core/Indexer/IndexerJson.cs | 1 - SnapX.Core/Indexer/IndexerText.cs | 1 - SnapX.Core/Indexer/IndexerXml.cs | 1 - SnapX.Core/Job/QuickTaskInfo.cs | 1 - SnapX.Core/Job/TaskEx.cs | 1 - SnapX.Core/Job/TaskHelpers.cs | 1 - SnapX.Core/Job/TaskInfo.cs | 1 - SnapX.Core/Job/TaskManager.cs | 1 - SnapX.Core/Job/TaskMetadata.cs | 1 - SnapX.Core/Job/TaskSettings.cs | 1 - SnapX.Core/Job/ThreadWorker.cs | 1 - SnapX.Core/Job/WorkerTask.cs | 1 - SnapX.Core/Media/Enums.cs | 1 - SnapX.Core/Media/ImageCombinerOptions.cs | 1 - SnapX.Core/Media/ScreenRecordManager.cs | 1 - SnapX.Core/Media/Screenshot_Transparent.cs | 1 - SnapX.Core/Media/VideoConverterOptions.cs | 1 - SnapX.Core/Media/VideoInfo.cs | 1 - SnapX.Core/Media/VideoThumbnailInfo.cs | 1 - SnapX.Core/Media/VideoThumbnailOptions.cs | 1 - SnapX.Core/Media/VideoThumbnailer.cs | 1 - SnapX.Core/SettingManager.cs | 1 - SnapX.Core/SharpCapture/Animations/BaseAnimation.cs | 1 - SnapX.Core/SharpCapture/Animations/ColorBlinkAnimation.cs | 1 - SnapX.Core/SharpCapture/Animations/PointAnimation.cs | 1 - SnapX.Core/SharpCapture/Animations/RectangleAnimation.cs | 1 - SnapX.Core/SharpCapture/Animations/TextAnimation.cs | 1 - SnapX.Core/SharpCapture/CaptureActiveMonitor.cs | 1 - SnapX.Core/SharpCapture/CaptureActiveWindow.cs | 1 - SnapX.Core/SharpCapture/CaptureBase.cs | 1 - SnapX.Core/SharpCapture/CaptureCustomRegion.cs | 1 - SnapX.Core/SharpCapture/CaptureCustomWindow.cs | 1 - SnapX.Core/SharpCapture/CaptureFullscreen.cs | 1 - SnapX.Core/SharpCapture/CaptureLastRegion.cs | 1 - SnapX.Core/SharpCapture/CaptureMonitor.cs | 1 - SnapX.Core/SharpCapture/CaptureRegion.cs | 1 - SnapX.Core/SharpCapture/CaptureWindow.cs | 1 - SnapX.Core/SharpCapture/Enums.cs | 1 - SnapX.Core/SharpCapture/Helpers/InputManager.cs | 1 - SnapX.Core/SharpCapture/Helpers/SimpleWindowInfo.cs | 1 - SnapX.Core/SharpCapture/Helpers/SnapSize.cs | 1 - SnapX.Core/SharpCapture/RegionCaptureOptions.cs | 1 - SnapX.Core/SharpCapture/ScreenRecording/FFmpegCaptureDevice.cs | 1 - SnapX.Core/SharpCapture/ScreenRecording/ImageCache.cs | 1 - SnapX.Core/SharpCapture/ScreenRecording/ScreenRecorder.cs | 1 - .../SharpCapture/ScreenRecording/ScreenRecordingOptions.cs | 1 - SnapX.Core/SnapXResources.cs | 1 - SnapX.Core/Upload/APIKeys.cs | 1 - SnapX.Core/Upload/BaseServices/FileUploaderService.cs | 1 - SnapX.Core/Upload/BaseServices/IGenericUploaderService.cs | 1 - SnapX.Core/Upload/BaseServices/IUploaderService.cs | 1 - SnapX.Core/Upload/BaseServices/ImageUploaderService.cs | 1 - SnapX.Core/Upload/BaseServices/TextUploaderService.cs | 1 - SnapX.Core/Upload/BaseServices/URLSharingService.cs | 1 - SnapX.Core/Upload/BaseServices/URLShortenerService.cs | 1 - SnapX.Core/Upload/BaseServices/UploaderService.cs | 1 - SnapX.Core/Upload/BaseUploaders/GenericUploader.cs | 1 - SnapX.Core/Upload/BaseUploaders/ImageUploader.cs | 1 - SnapX.Core/Upload/BaseUploaders/TextUploader.cs | 1 - SnapX.Core/Upload/BaseUploaders/URLSharer.cs | 1 - SnapX.Core/Upload/BaseUploaders/URLShortener.cs | 1 - SnapX.Core/Upload/BaseUploaders/Uploader.cs | 1 - SnapX.Core/Upload/Custom/CustomUploaderInput.cs | 1 - SnapX.Core/Upload/Custom/CustomUploaderItem.cs | 1 - SnapX.Core/Upload/Custom/Functions/CustomUploaderFunction.cs | 1 - .../Upload/Custom/Functions/CustomUploaderFunctionBase64.cs | 1 - .../Upload/Custom/Functions/CustomUploaderFunctionFileName.cs | 1 - .../Upload/Custom/Functions/CustomUploaderFunctionHeader.cs | 1 - .../Upload/Custom/Functions/CustomUploaderFunctionInput.cs | 1 - .../Upload/Custom/Functions/CustomUploaderFunctionInputBox.cs | 1 - SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionJson.cs | 1 - .../Upload/Custom/Functions/CustomUploaderFunctionOutputBox.cs | 1 - .../Upload/Custom/Functions/CustomUploaderFunctionRandom.cs | 1 - .../Upload/Custom/Functions/CustomUploaderFunctionRegex.cs | 1 - .../Upload/Custom/Functions/CustomUploaderFunctionResponse.cs | 1 - .../Upload/Custom/Functions/CustomUploaderFunctionResponseURL.cs | 1 - .../Upload/Custom/Functions/CustomUploaderFunctionSelect.cs | 1 - SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionXml.cs | 1 - SnapX.Core/Upload/Custom/ShareXCustomUploaderSyntaxParser.cs | 1 - SnapX.Core/Upload/Custom/ShareXSyntaxParser.cs | 1 - SnapX.Core/Upload/File/AmazonS3.cs | 1 - SnapX.Core/Upload/File/AmazonS3Endpoint.cs | 1 - SnapX.Core/Upload/File/AmazonS3Settings.cs | 1 - SnapX.Core/Upload/File/AzureStorage.cs | 1 - SnapX.Core/Upload/File/BackblazeB2.cs | 1 - SnapX.Core/Upload/File/Box.cs | 1 - SnapX.Core/Upload/File/Copy.cs | 1 - SnapX.Core/Upload/File/CustomFileUploader.cs | 1 - SnapX.Core/Upload/File/DropIO.cs | 1 - SnapX.Core/Upload/File/Dropbox.cs | 1 - SnapX.Core/Upload/File/Email.cs | 1 - SnapX.Core/Upload/File/FTP.cs | 1 - SnapX.Core/Upload/File/FTPAccount.cs | 1 - SnapX.Core/Upload/File/FileBin.cs | 1 - SnapX.Core/Upload/File/FileSonic.cs | 1 - SnapX.Core/Upload/File/GoogleCloudStorage.cs | 1 - SnapX.Core/Upload/File/GoogleDrive.cs | 1 - SnapX.Core/Upload/File/Hostr.cs | 1 - SnapX.Core/Upload/File/Jira.cs | 1 - SnapX.Core/Upload/File/Lambda.cs | 1 - SnapX.Core/Upload/File/LobFile.cs | 1 - SnapX.Core/Upload/File/LocalhostAccount.cs | 1 - SnapX.Core/Upload/File/MediaFire.cs | 1 - SnapX.Core/Upload/File/Mega.cs | 1 - SnapX.Core/Upload/File/MegaAuthInfos.cs | 1 - SnapX.Core/Upload/File/OneDrive.cs | 1 - SnapX.Core/Upload/File/OwnCloud.cs | 1 - SnapX.Core/Upload/File/Plik.cs | 1 - SnapX.Core/Upload/File/PlikSettings.cs | 1 - SnapX.Core/Upload/File/Pomf.cs | 1 - SnapX.Core/Upload/File/PomfUploader.cs | 1 - SnapX.Core/Upload/File/Pushbullet.cs | 1 - SnapX.Core/Upload/File/Puush.cs | 1 - SnapX.Core/Upload/File/SFTP.cs | 1 - SnapX.Core/Upload/File/Seafile.cs | 1 - SnapX.Core/Upload/File/SendSpace.cs | 1 - SnapX.Core/Upload/File/SendSpaceManager.cs | 1 - SnapX.Core/Upload/File/ShareCX.cs | 1 - SnapX.Core/Upload/File/SharedFolderUploader.cs | 1 - SnapX.Core/Upload/File/Streamable.cs | 1 - SnapX.Core/Upload/File/Sul.cs | 1 - SnapX.Core/Upload/File/Transfersh.cs | 1 - SnapX.Core/Upload/File/Uguu.cs | 1 - SnapX.Core/Upload/File/Vault_ooo.cs | 1 - SnapX.Core/Upload/File/YouTube.cs | 1 - SnapX.Core/Upload/Img/Chevereto.cs | 1 - SnapX.Core/Upload/Img/CheveretoUploader.cs | 1 - SnapX.Core/Upload/Img/CustomImageUploader.cs | 1 - SnapX.Core/Upload/Img/FlickrUploader.cs | 1 - SnapX.Core/Upload/Img/ImageBin.cs | 1 - SnapX.Core/Upload/Img/ImageShackUploader.cs | 1 - SnapX.Core/Upload/Img/Img1Uploader.cs | 1 - SnapX.Core/Upload/Img/Imgur.cs | 1 - SnapX.Core/Upload/Img/ImmioUploader.cs | 1 - SnapX.Core/Upload/Img/Photobucket.cs | 1 - SnapX.Core/Upload/Img/TwitPicUploader.cs | 1 - SnapX.Core/Upload/Img/TwitSnapsUploader.cs | 1 - SnapX.Core/Upload/Img/Twitter.cs | 1 - SnapX.Core/Upload/Img/UploadScreenshot.cs | 1 - SnapX.Core/Upload/Img/VgymeUploader.cs | 1 - SnapX.Core/Upload/Img/YfrogUploader.cs | 1 - SnapX.Core/Upload/OAuth/GoogleOAuth2.cs | 1 - SnapX.Core/Upload/OAuth/IOAuth.cs | 1 - SnapX.Core/Upload/OAuth/IOAuth2.cs | 1 - SnapX.Core/Upload/OAuth/IOAuth2Basic.cs | 1 - SnapX.Core/Upload/OAuth/IOAuthBase.cs | 1 - SnapX.Core/Upload/OAuth/IOauth2Loopback.cs | 1 - SnapX.Core/Upload/OAuth/OAuth2Info.cs | 1 - SnapX.Core/Upload/OAuth/OAuth2ProofKey.cs | 1 - SnapX.Core/Upload/OAuth/OAuth2Token.cs | 1 - SnapX.Core/Upload/OAuth/OAuthInfo.cs | 1 - SnapX.Core/Upload/OAuth/OAuthListener.cs | 1 - SnapX.Core/Upload/OAuth/OAuthManager.cs | 1 - SnapX.Core/Upload/OAuth/OAuthUserInfo.cs | 1 - .../Upload/SharingServices/BingVisualSearchSharingService.cs | 1 - SnapX.Core/Upload/SharingServices/CustomURLSharingService.cs | 1 - SnapX.Core/Upload/SharingServices/DeliciousSharingService.cs | 1 - SnapX.Core/Upload/SharingServices/EmailSharingService.cs | 1 - SnapX.Core/Upload/SharingServices/FacebookSharingService.cs | 1 - SnapX.Core/Upload/SharingServices/GoogleLensSharingService.cs | 1 - SnapX.Core/Upload/SharingServices/LinkedInSharingService.cs | 1 - SnapX.Core/Upload/SharingServices/PinterestSharingService.cs | 1 - SnapX.Core/Upload/SharingServices/PushbulletSharingService.cs | 1 - SnapX.Core/Upload/SharingServices/RedditSharingService.cs | 1 - SnapX.Core/Upload/SharingServices/SimpleURLSharingService.cs | 1 - SnapX.Core/Upload/SharingServices/StumbleUponSharingService.cs | 1 - SnapX.Core/Upload/SharingServices/TumblrSharingService.cs | 1 - SnapX.Core/Upload/SharingServices/TwitterSharingService.cs | 1 - SnapX.Core/Upload/SharingServices/VkSharingService.cs | 1 - SnapX.Core/Upload/Text/CustomTextUploader.cs | 1 - SnapX.Core/Upload/Text/GitHubGist.cs | 1 - SnapX.Core/Upload/Text/Hastebin.cs | 1 - SnapX.Core/Upload/Text/OneTimeSecret.cs | 1 - SnapX.Core/Upload/Text/Paste2.cs | 1 - SnapX.Core/Upload/Text/Paste_ee.cs | 1 - SnapX.Core/Upload/Text/Pastebin.cs | 1 - SnapX.Core/Upload/Text/Pastebin_ca.cs | 1 - SnapX.Core/Upload/Text/Pastie.cs | 1 - SnapX.Core/Upload/Text/Slexy.cs | 1 - SnapX.Core/Upload/Text/Upaste.cs | 1 - SnapX.Core/Upload/URL/BitlyURLShortener.cs | 1 - SnapX.Core/Upload/URL/CustomURLShortener.cs | 1 - SnapX.Core/Upload/URL/FirebaseDynamicLinksURLShortener.cs | 1 - SnapX.Core/Upload/URL/IsgdURLShortener.cs | 1 - SnapX.Core/Upload/URL/KuttURLShortener.cs | 1 - SnapX.Core/Upload/URL/NlcmURLShortener.cs | 1 - SnapX.Core/Upload/URL/PolrURLShortener.cs | 1 - SnapX.Core/Upload/URL/QRnetURLShortener.cs | 1 - SnapX.Core/Upload/URL/TinyURLShortener.cs | 1 - SnapX.Core/Upload/URL/TurlURLShortener.cs | 1 - SnapX.Core/Upload/URL/TwoGPURLShortener.cs | 1 - SnapX.Core/Upload/URL/VURLShortener.cs | 1 - SnapX.Core/Upload/URL/VgdURLShortener.cs | 1 - SnapX.Core/Upload/URL/YourlsURLShortener.cs | 1 - SnapX.Core/Upload/URL/ZeroWidthURLShortener.cs | 1 - SnapX.Core/Upload/UploadInfoManager.cs | 1 - SnapX.Core/Upload/UploadInfoParser.cs | 1 - SnapX.Core/Upload/UploadInfoStatus.cs | 1 - SnapX.Core/Upload/UploadManager.cs | 1 - SnapX.Core/Upload/UploadResult.cs | 1 - SnapX.Core/Upload/UploaderFactory.cs | 1 - SnapX.Core/Upload/UploaderFilter.cs | 1 - SnapX.Core/Upload/UploadersConfig.cs | 1 - SnapX.Core/Upload/UploadersConfigValidator.cs | 1 - SnapX.Core/Upload/Utils/AccountInfo.cs | 1 - SnapX.Core/Upload/Utils/Argument.cs | 1 - SnapX.Core/Upload/Utils/EscapeHelper.cs | 1 - SnapX.Core/Upload/Utils/ProgressManager.cs | 1 - SnapX.Core/Upload/Utils/RequestHelpers.cs | 1 - SnapX.Core/Upload/Utils/ResponseInfo.cs | 1 - SnapX.Core/Upload/Utils/SSLBypassHelper.cs | 1 - SnapX.Core/Upload/Utils/TaskReferenceHelper.cs | 1 - SnapX.Core/Upload/Utils/UploaderErrorInfo.cs | 1 - SnapX.Core/Upload/Utils/UploaderErrorManager.cs | 1 - SnapX.Core/Upload/Zip/ZipEntryInfo.cs | 1 - SnapX.Core/Upload/Zip/ZipManager.cs | 1 - SnapX.Core/Utils/CaptureHelpers.cs | 1 - SnapX.Core/Utils/Cryptographic/HashChecker.cs | 1 - SnapX.Core/Utils/Cryptographic/Translator.cs | 1 - SnapX.Core/Utils/Cryptographic/TranslatorHelper.cs | 1 - SnapX.Core/Utils/DNS/AdapterInfo.cs | 1 - SnapX.Core/Utils/DNS/DNSInfo.cs | 1 - SnapX.Core/Utils/Extensions/EnumExtensions.cs | 1 - SnapX.Core/Utils/Extensions/Extensions.cs | 1 - SnapX.Core/Utils/Extensions/NumberExtensions.cs | 1 - SnapX.Core/Utils/Extensions/ObjectExtensions.cs | 1 - SnapX.Core/Utils/Extensions/StreamExtensions.cs | 1 - SnapX.Core/Utils/Extensions/StringExtensions.cs | 1 - SnapX.Core/Utils/Extensions/XMLExtensions.cs | 1 - SnapX.Core/Utils/FileDownloader.cs | 1 - SnapX.Core/Utils/FileHelpers.cs | 1 - SnapX.Core/Utils/Helpers.cs | 1 - SnapX.Core/Utils/JsonHelpers.cs | 1 - SnapX.Core/Utils/MathHelpers.cs | 1 - SnapX.Core/Utils/Miscellaneous/ExternalProgram.cs | 1 - SnapX.Core/Utils/Miscellaneous/FPSManager.cs | 1 - SnapX.Core/Utils/Miscellaneous/FastDateTime.cs | 1 - SnapX.Core/Utils/Miscellaneous/FixedSizedQueue.cs | 1 - SnapX.Core/Utils/Miscellaneous/HelpersOptions.cs | 1 - SnapX.Core/Utils/Miscellaneous/HttpClientFactory.cs | 1 - SnapX.Core/Utils/Miscellaneous/Links.cs | 1 - SnapX.Core/Utils/Miscellaneous/MaxLengthStream.cs | 1 - SnapX.Core/Utils/Miscellaneous/MimeTypesPlus.cs | 1 - SnapX.Core/Utils/Miscellaneous/PingHelper.cs | 1 - SnapX.Core/Utils/Miscellaneous/PingResult.cs | 1 - SnapX.Core/Utils/Miscellaneous/ProxyInfo.cs | 1 - SnapX.Core/Utils/Miscellaneous/SevenZipManager.cs | 1 - SnapX.Core/Utils/Miscellaneous/StringLineReader.cs | 1 - SnapX.Core/Utils/Parsers/CodeMenuEntry.cs | 1 - SnapX.Core/Utils/Random/RandomCrypto.cs | 1 - SnapX.Core/Utils/Random/RandomFast.cs | 1 - SnapX.Core/Utils/URLHelpers.cs | 1 - SnapX.Core/Utils/WebHelpers.cs | 1 - SnapX.Core/Watch/WatchFolder.cs | 1 - SnapX.Core/Watch/WatchFolderManager.cs | 1 - SnapX.Core/Watch/WatchFolderSettings.cs | 1 - 326 files changed, 326 deletions(-) diff --git a/SnapX.Core/CLI/CLICommand.cs b/SnapX.Core/CLI/CLICommand.cs index 3426f2203..515f0c381 100644 --- a/SnapX.Core/CLI/CLICommand.cs +++ b/SnapX.Core/CLI/CLICommand.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/CLI/CLICommandAction.cs b/SnapX.Core/CLI/CLICommandAction.cs index 5d0918348..154ef8b7b 100644 --- a/SnapX.Core/CLI/CLICommandAction.cs +++ b/SnapX.Core/CLI/CLICommandAction.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/CLI/CLIManager.cs b/SnapX.Core/CLI/CLIManager.cs index 43af96297..d25ae4a5f 100644 --- a/SnapX.Core/CLI/CLIManager.cs +++ b/SnapX.Core/CLI/CLIManager.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/CLI/ExternalCLIManager.cs b/SnapX.Core/CLI/ExternalCLIManager.cs index 84106b3a6..ed66914c4 100644 --- a/SnapX.Core/CLI/ExternalCLIManager.cs +++ b/SnapX.Core/CLI/ExternalCLIManager.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/CLI/NativeMessageInput.cs b/SnapX.Core/CLI/NativeMessageInput.cs index 04a6be556..d4d366ada 100644 --- a/SnapX.Core/CLI/NativeMessageInput.cs +++ b/SnapX.Core/CLI/NativeMessageInput.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/CLI/NativeMessagingHost.cs b/SnapX.Core/CLI/NativeMessagingHost.cs index 867194258..4625f630b 100644 --- a/SnapX.Core/CLI/NativeMessagingHost.cs +++ b/SnapX.Core/CLI/NativeMessagingHost.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Enums.cs b/SnapX.Core/Enums.cs index e796758da..47cc8780b 100644 --- a/SnapX.Core/Enums.cs +++ b/SnapX.Core/Enums.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/History/HistoryFilter.cs b/SnapX.Core/History/HistoryFilter.cs index 62acea2bc..b9f5ea2f3 100644 --- a/SnapX.Core/History/HistoryFilter.cs +++ b/SnapX.Core/History/HistoryFilter.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/History/HistoryItem.cs b/SnapX.Core/History/HistoryItem.cs index 21dbb3dff..a5ddde2a9 100644 --- a/SnapX.Core/History/HistoryItem.cs +++ b/SnapX.Core/History/HistoryItem.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/History/HistoryItemManager.cs b/SnapX.Core/History/HistoryItemManager.cs index 74e4c1476..d35e0eadc 100644 --- a/SnapX.Core/History/HistoryItemManager.cs +++ b/SnapX.Core/History/HistoryItemManager.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/History/HistoryManager.cs b/SnapX.Core/History/HistoryManager.cs index 1942d1bc2..300a683c8 100644 --- a/SnapX.Core/History/HistoryManager.cs +++ b/SnapX.Core/History/HistoryManager.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/History/HistorySettings.cs b/SnapX.Core/History/HistorySettings.cs index ce9352a3d..bfec22095 100644 --- a/SnapX.Core/History/HistorySettings.cs +++ b/SnapX.Core/History/HistorySettings.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Hotkey/HotkeyManager.cs b/SnapX.Core/Hotkey/HotkeyManager.cs index 0826ed7b8..9780ec539 100644 --- a/SnapX.Core/Hotkey/HotkeyManager.cs +++ b/SnapX.Core/Hotkey/HotkeyManager.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Hotkey/HotkeySettings.cs b/SnapX.Core/Hotkey/HotkeySettings.cs index 7e431a0b9..2a88926e4 100644 --- a/SnapX.Core/Hotkey/HotkeySettings.cs +++ b/SnapX.Core/Hotkey/HotkeySettings.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Adjustments/Alpha.cs b/SnapX.Core/ImageEffects/Adjustments/Alpha.cs index 55698c753..c77943e85 100644 --- a/SnapX.Core/ImageEffects/Adjustments/Alpha.cs +++ b/SnapX.Core/ImageEffects/Adjustments/Alpha.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Adjustments/BlackWhite.cs b/SnapX.Core/ImageEffects/Adjustments/BlackWhite.cs index 409dea6f9..e17ccd86d 100644 --- a/SnapX.Core/ImageEffects/Adjustments/BlackWhite.cs +++ b/SnapX.Core/ImageEffects/Adjustments/BlackWhite.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Adjustments/Brightness.cs b/SnapX.Core/ImageEffects/Adjustments/Brightness.cs index cdcee5f62..c9ae78d88 100644 --- a/SnapX.Core/ImageEffects/Adjustments/Brightness.cs +++ b/SnapX.Core/ImageEffects/Adjustments/Brightness.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Adjustments/Colorize.cs b/SnapX.Core/ImageEffects/Adjustments/Colorize.cs index 1d3fac252..f4d82558d 100644 --- a/SnapX.Core/ImageEffects/Adjustments/Colorize.cs +++ b/SnapX.Core/ImageEffects/Adjustments/Colorize.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Adjustments/Contrast.cs b/SnapX.Core/ImageEffects/Adjustments/Contrast.cs index 82ef6164a..d7b19ba90 100644 --- a/SnapX.Core/ImageEffects/Adjustments/Contrast.cs +++ b/SnapX.Core/ImageEffects/Adjustments/Contrast.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Adjustments/Gamma.cs b/SnapX.Core/ImageEffects/Adjustments/Gamma.cs index 82920e931..c72f97cd6 100644 --- a/SnapX.Core/ImageEffects/Adjustments/Gamma.cs +++ b/SnapX.Core/ImageEffects/Adjustments/Gamma.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Adjustments/Grayscale.cs b/SnapX.Core/ImageEffects/Adjustments/Grayscale.cs index 650dab33e..041659e0f 100644 --- a/SnapX.Core/ImageEffects/Adjustments/Grayscale.cs +++ b/SnapX.Core/ImageEffects/Adjustments/Grayscale.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Adjustments/Hue.cs b/SnapX.Core/ImageEffects/Adjustments/Hue.cs index dddb5d6a0..8a110ab2f 100644 --- a/SnapX.Core/ImageEffects/Adjustments/Hue.cs +++ b/SnapX.Core/ImageEffects/Adjustments/Hue.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Adjustments/MatrixColor.cs b/SnapX.Core/ImageEffects/Adjustments/MatrixColor.cs index 7a6c50911..177bff51f 100644 --- a/SnapX.Core/ImageEffects/Adjustments/MatrixColor.cs +++ b/SnapX.Core/ImageEffects/Adjustments/MatrixColor.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Adjustments/ReplaceColor.cs b/SnapX.Core/ImageEffects/Adjustments/ReplaceColor.cs index 568aa47c2..a034b8b09 100644 --- a/SnapX.Core/ImageEffects/Adjustments/ReplaceColor.cs +++ b/SnapX.Core/ImageEffects/Adjustments/ReplaceColor.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Adjustments/Saturation.cs b/SnapX.Core/ImageEffects/Adjustments/Saturation.cs index 727a48604..a62dff0f9 100644 --- a/SnapX.Core/ImageEffects/Adjustments/Saturation.cs +++ b/SnapX.Core/ImageEffects/Adjustments/Saturation.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Adjustments/SelectiveColor.cs b/SnapX.Core/ImageEffects/Adjustments/SelectiveColor.cs index 01c398cfc..274b4f423 100644 --- a/SnapX.Core/ImageEffects/Adjustments/SelectiveColor.cs +++ b/SnapX.Core/ImageEffects/Adjustments/SelectiveColor.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Adjustments/Sepia.cs b/SnapX.Core/ImageEffects/Adjustments/Sepia.cs index 0a347fd2d..ccf01e698 100644 --- a/SnapX.Core/ImageEffects/Adjustments/Sepia.cs +++ b/SnapX.Core/ImageEffects/Adjustments/Sepia.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Drawings/DrawBackground.cs b/SnapX.Core/ImageEffects/Drawings/DrawBackground.cs index f1fbf980a..4740afff4 100644 --- a/SnapX.Core/ImageEffects/Drawings/DrawBackground.cs +++ b/SnapX.Core/ImageEffects/Drawings/DrawBackground.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Drawings/DrawBackgroundImage.cs b/SnapX.Core/ImageEffects/Drawings/DrawBackgroundImage.cs index db82694f6..3bad927a9 100644 --- a/SnapX.Core/ImageEffects/Drawings/DrawBackgroundImage.cs +++ b/SnapX.Core/ImageEffects/Drawings/DrawBackgroundImage.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Drawings/DrawBorder.cs b/SnapX.Core/ImageEffects/Drawings/DrawBorder.cs index 88eef2fa7..887c880c6 100644 --- a/SnapX.Core/ImageEffects/Drawings/DrawBorder.cs +++ b/SnapX.Core/ImageEffects/Drawings/DrawBorder.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Drawings/DrawCheckerboard.cs b/SnapX.Core/ImageEffects/Drawings/DrawCheckerboard.cs index f6e6681af..6c7ed65ce 100644 --- a/SnapX.Core/ImageEffects/Drawings/DrawCheckerboard.cs +++ b/SnapX.Core/ImageEffects/Drawings/DrawCheckerboard.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Drawings/DrawImage.cs b/SnapX.Core/ImageEffects/Drawings/DrawImage.cs index 87db843cc..29d9a67ff 100644 --- a/SnapX.Core/ImageEffects/Drawings/DrawImage.cs +++ b/SnapX.Core/ImageEffects/Drawings/DrawImage.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Drawings/DrawParticles.cs b/SnapX.Core/ImageEffects/Drawings/DrawParticles.cs index 7fc391bc0..7187140e7 100644 --- a/SnapX.Core/ImageEffects/Drawings/DrawParticles.cs +++ b/SnapX.Core/ImageEffects/Drawings/DrawParticles.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Drawings/DrawText.cs b/SnapX.Core/ImageEffects/Drawings/DrawText.cs index 5d9e56e5c..e14038102 100644 --- a/SnapX.Core/ImageEffects/Drawings/DrawText.cs +++ b/SnapX.Core/ImageEffects/Drawings/DrawText.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Drawings/DrawTextEx.cs b/SnapX.Core/ImageEffects/Drawings/DrawTextEx.cs index b0acd2b4f..460b9a94e 100644 --- a/SnapX.Core/ImageEffects/Drawings/DrawTextEx.cs +++ b/SnapX.Core/ImageEffects/Drawings/DrawTextEx.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Enums.cs b/SnapX.Core/ImageEffects/Enums.cs index 758e38883..6dc5595e7 100644 --- a/SnapX.Core/ImageEffects/Enums.cs +++ b/SnapX.Core/ImageEffects/Enums.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Filters/Blur.cs b/SnapX.Core/ImageEffects/Filters/Blur.cs index 95488c96a..c87aecf1d 100644 --- a/SnapX.Core/ImageEffects/Filters/Blur.cs +++ b/SnapX.Core/ImageEffects/Filters/Blur.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Filters/EdgeDetect.cs b/SnapX.Core/ImageEffects/Filters/EdgeDetect.cs index 1cc2652eb..803f08a78 100644 --- a/SnapX.Core/ImageEffects/Filters/EdgeDetect.cs +++ b/SnapX.Core/ImageEffects/Filters/EdgeDetect.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Filters/Emboss.cs b/SnapX.Core/ImageEffects/Filters/Emboss.cs index 58b66c69c..b1b17cb1a 100644 --- a/SnapX.Core/ImageEffects/Filters/Emboss.cs +++ b/SnapX.Core/ImageEffects/Filters/Emboss.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later using System.Numerics; diff --git a/SnapX.Core/ImageEffects/Filters/GaussianBlur.cs b/SnapX.Core/ImageEffects/Filters/GaussianBlur.cs index a82b31934..19a008c97 100644 --- a/SnapX.Core/ImageEffects/Filters/GaussianBlur.cs +++ b/SnapX.Core/ImageEffects/Filters/GaussianBlur.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later using System.ComponentModel; diff --git a/SnapX.Core/ImageEffects/Filters/Glow.cs b/SnapX.Core/ImageEffects/Filters/Glow.cs index 2887b8cd5..f15eeba63 100644 --- a/SnapX.Core/ImageEffects/Filters/Glow.cs +++ b/SnapX.Core/ImageEffects/Filters/Glow.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Filters/MatrixConvolution.cs b/SnapX.Core/ImageEffects/Filters/MatrixConvolution.cs index fb3864983..0fdafce45 100644 --- a/SnapX.Core/ImageEffects/Filters/MatrixConvolution.cs +++ b/SnapX.Core/ImageEffects/Filters/MatrixConvolution.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Filters/MeanRemoval.cs b/SnapX.Core/ImageEffects/Filters/MeanRemoval.cs index 20170729b..74d8291a0 100644 --- a/SnapX.Core/ImageEffects/Filters/MeanRemoval.cs +++ b/SnapX.Core/ImageEffects/Filters/MeanRemoval.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Filters/Outline.cs b/SnapX.Core/ImageEffects/Filters/Outline.cs index d65ae6b63..865ee9a00 100644 --- a/SnapX.Core/ImageEffects/Filters/Outline.cs +++ b/SnapX.Core/ImageEffects/Filters/Outline.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Filters/Pixelate.cs b/SnapX.Core/ImageEffects/Filters/Pixelate.cs index 0bf7280dd..c0f10578a 100644 --- a/SnapX.Core/ImageEffects/Filters/Pixelate.cs +++ b/SnapX.Core/ImageEffects/Filters/Pixelate.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Filters/RGBSplit.cs b/SnapX.Core/ImageEffects/Filters/RGBSplit.cs index 3bbf133d4..5be9366ab 100644 --- a/SnapX.Core/ImageEffects/Filters/RGBSplit.cs +++ b/SnapX.Core/ImageEffects/Filters/RGBSplit.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Filters/Reflection.cs b/SnapX.Core/ImageEffects/Filters/Reflection.cs index 32a833a01..bfb9fb3a8 100644 --- a/SnapX.Core/ImageEffects/Filters/Reflection.cs +++ b/SnapX.Core/ImageEffects/Filters/Reflection.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Filters/Shadow.cs b/SnapX.Core/ImageEffects/Filters/Shadow.cs index e376c25d9..da3690395 100644 --- a/SnapX.Core/ImageEffects/Filters/Shadow.cs +++ b/SnapX.Core/ImageEffects/Filters/Shadow.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Filters/Slice.cs b/SnapX.Core/ImageEffects/Filters/Slice.cs index 552c540e3..26ec405a7 100644 --- a/SnapX.Core/ImageEffects/Filters/Slice.cs +++ b/SnapX.Core/ImageEffects/Filters/Slice.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Filters/TornEdge.cs b/SnapX.Core/ImageEffects/Filters/TornEdge.cs index e129205ef..e6470b9e2 100644 --- a/SnapX.Core/ImageEffects/Filters/TornEdge.cs +++ b/SnapX.Core/ImageEffects/Filters/TornEdge.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Filters/WaveEdge.cs b/SnapX.Core/ImageEffects/Filters/WaveEdge.cs index c940e1b00..6336e604c 100644 --- a/SnapX.Core/ImageEffects/Filters/WaveEdge.cs +++ b/SnapX.Core/ImageEffects/Filters/WaveEdge.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/ImageEffect.cs b/SnapX.Core/ImageEffects/ImageEffect.cs index ae833b876..07c733244 100644 --- a/SnapX.Core/ImageEffects/ImageEffect.cs +++ b/SnapX.Core/ImageEffects/ImageEffect.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/ImageEffectPackager.cs b/SnapX.Core/ImageEffects/ImageEffectPackager.cs index 7a69aeac5..67b9a256a 100644 --- a/SnapX.Core/ImageEffects/ImageEffectPackager.cs +++ b/SnapX.Core/ImageEffects/ImageEffectPackager.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/ImageEffectPreset.cs b/SnapX.Core/ImageEffects/ImageEffectPreset.cs index 1e2e7028e..62bae19d0 100644 --- a/SnapX.Core/ImageEffects/ImageEffectPreset.cs +++ b/SnapX.Core/ImageEffects/ImageEffectPreset.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Manipulations/AutoCrop.cs b/SnapX.Core/ImageEffects/Manipulations/AutoCrop.cs index 1b4e3e1eb..bdb5c8712 100644 --- a/SnapX.Core/ImageEffects/Manipulations/AutoCrop.cs +++ b/SnapX.Core/ImageEffects/Manipulations/AutoCrop.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Manipulations/Canvas.cs b/SnapX.Core/ImageEffects/Manipulations/Canvas.cs index be0102ef6..259e2db05 100644 --- a/SnapX.Core/ImageEffects/Manipulations/Canvas.cs +++ b/SnapX.Core/ImageEffects/Manipulations/Canvas.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Manipulations/Crop.cs b/SnapX.Core/ImageEffects/Manipulations/Crop.cs index becc2a8db..47beb3c51 100644 --- a/SnapX.Core/ImageEffects/Manipulations/Crop.cs +++ b/SnapX.Core/ImageEffects/Manipulations/Crop.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Manipulations/Flip.cs b/SnapX.Core/ImageEffects/Manipulations/Flip.cs index 36e8e718d..43b51050e 100644 --- a/SnapX.Core/ImageEffects/Manipulations/Flip.cs +++ b/SnapX.Core/ImageEffects/Manipulations/Flip.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Manipulations/ForceProportions.cs b/SnapX.Core/ImageEffects/Manipulations/ForceProportions.cs index 44094f211..0059b2b12 100644 --- a/SnapX.Core/ImageEffects/Manipulations/ForceProportions.cs +++ b/SnapX.Core/ImageEffects/Manipulations/ForceProportions.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Manipulations/Resize.cs b/SnapX.Core/ImageEffects/Manipulations/Resize.cs index 804cf00ce..9cd4ab7e3 100644 --- a/SnapX.Core/ImageEffects/Manipulations/Resize.cs +++ b/SnapX.Core/ImageEffects/Manipulations/Resize.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Manipulations/Rotate.cs b/SnapX.Core/ImageEffects/Manipulations/Rotate.cs index b5c66df1d..07da43dae 100644 --- a/SnapX.Core/ImageEffects/Manipulations/Rotate.cs +++ b/SnapX.Core/ImageEffects/Manipulations/Rotate.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Manipulations/RoundedCorners.cs b/SnapX.Core/ImageEffects/Manipulations/RoundedCorners.cs index 6f79c32f0..71fabcb97 100644 --- a/SnapX.Core/ImageEffects/Manipulations/RoundedCorners.cs +++ b/SnapX.Core/ImageEffects/Manipulations/RoundedCorners.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Manipulations/Scale.cs b/SnapX.Core/ImageEffects/Manipulations/Scale.cs index e5136c876..72e642e5d 100644 --- a/SnapX.Core/ImageEffects/Manipulations/Scale.cs +++ b/SnapX.Core/ImageEffects/Manipulations/Scale.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/Manipulations/Skew.cs b/SnapX.Core/ImageEffects/Manipulations/Skew.cs index 20e385e48..3eec948e3 100644 --- a/SnapX.Core/ImageEffects/Manipulations/Skew.cs +++ b/SnapX.Core/ImageEffects/Manipulations/Skew.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/ImageEffects/WatermarkConfig.cs b/SnapX.Core/ImageEffects/WatermarkConfig.cs index 9064f9914..8d1f6e861 100644 --- a/SnapX.Core/ImageEffects/WatermarkConfig.cs +++ b/SnapX.Core/ImageEffects/WatermarkConfig.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Indexer/Enums.cs b/SnapX.Core/Indexer/Enums.cs index b4223d0d1..1cb3d89eb 100644 --- a/SnapX.Core/Indexer/Enums.cs +++ b/SnapX.Core/Indexer/Enums.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Indexer/FolderInfo.cs b/SnapX.Core/Indexer/FolderInfo.cs index 111e90ea6..6f2ab5153 100644 --- a/SnapX.Core/Indexer/FolderInfo.cs +++ b/SnapX.Core/Indexer/FolderInfo.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Indexer/HtmlHelper.cs b/SnapX.Core/Indexer/HtmlHelper.cs index aea79303a..5d53acc34 100644 --- a/SnapX.Core/Indexer/HtmlHelper.cs +++ b/SnapX.Core/Indexer/HtmlHelper.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Indexer/Indexer.cs b/SnapX.Core/Indexer/Indexer.cs index 07e7d8bd0..56a287f61 100644 --- a/SnapX.Core/Indexer/Indexer.cs +++ b/SnapX.Core/Indexer/Indexer.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Indexer/IndexerHtml.cs b/SnapX.Core/Indexer/IndexerHtml.cs index 977a1532b..ef20c5475 100644 --- a/SnapX.Core/Indexer/IndexerHtml.cs +++ b/SnapX.Core/Indexer/IndexerHtml.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Indexer/IndexerJson.cs b/SnapX.Core/Indexer/IndexerJson.cs index b2be409a5..9272a4488 100644 --- a/SnapX.Core/Indexer/IndexerJson.cs +++ b/SnapX.Core/Indexer/IndexerJson.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Indexer/IndexerText.cs b/SnapX.Core/Indexer/IndexerText.cs index 8a0f830fc..6369aa25c 100644 --- a/SnapX.Core/Indexer/IndexerText.cs +++ b/SnapX.Core/Indexer/IndexerText.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Indexer/IndexerXml.cs b/SnapX.Core/Indexer/IndexerXml.cs index ed9ada1ee..69c241cb4 100644 --- a/SnapX.Core/Indexer/IndexerXml.cs +++ b/SnapX.Core/Indexer/IndexerXml.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Job/QuickTaskInfo.cs b/SnapX.Core/Job/QuickTaskInfo.cs index c57601a16..bd61edcb3 100644 --- a/SnapX.Core/Job/QuickTaskInfo.cs +++ b/SnapX.Core/Job/QuickTaskInfo.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Job/TaskEx.cs b/SnapX.Core/Job/TaskEx.cs index 18eea9f7b..12a486a19 100644 --- a/SnapX.Core/Job/TaskEx.cs +++ b/SnapX.Core/Job/TaskEx.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Job/TaskHelpers.cs b/SnapX.Core/Job/TaskHelpers.cs index bcdd08732..b8161f3a7 100644 --- a/SnapX.Core/Job/TaskHelpers.cs +++ b/SnapX.Core/Job/TaskHelpers.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Job/TaskInfo.cs b/SnapX.Core/Job/TaskInfo.cs index bf143ba64..7fa0c250b 100644 --- a/SnapX.Core/Job/TaskInfo.cs +++ b/SnapX.Core/Job/TaskInfo.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Job/TaskManager.cs b/SnapX.Core/Job/TaskManager.cs index 940f13c0b..00684ec67 100644 --- a/SnapX.Core/Job/TaskManager.cs +++ b/SnapX.Core/Job/TaskManager.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Job/TaskMetadata.cs b/SnapX.Core/Job/TaskMetadata.cs index e683a3094..27ac79699 100644 --- a/SnapX.Core/Job/TaskMetadata.cs +++ b/SnapX.Core/Job/TaskMetadata.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Job/TaskSettings.cs b/SnapX.Core/Job/TaskSettings.cs index 30718d8ab..529a1d47e 100644 --- a/SnapX.Core/Job/TaskSettings.cs +++ b/SnapX.Core/Job/TaskSettings.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Job/ThreadWorker.cs b/SnapX.Core/Job/ThreadWorker.cs index 3b05d21a4..5f91ab36e 100644 --- a/SnapX.Core/Job/ThreadWorker.cs +++ b/SnapX.Core/Job/ThreadWorker.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Job/WorkerTask.cs b/SnapX.Core/Job/WorkerTask.cs index 147ebcaf1..328f9e6ba 100644 --- a/SnapX.Core/Job/WorkerTask.cs +++ b/SnapX.Core/Job/WorkerTask.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Media/Enums.cs b/SnapX.Core/Media/Enums.cs index e4f31497f..a56181466 100644 --- a/SnapX.Core/Media/Enums.cs +++ b/SnapX.Core/Media/Enums.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Media/ImageCombinerOptions.cs b/SnapX.Core/Media/ImageCombinerOptions.cs index 19d66ad65..340a62008 100644 --- a/SnapX.Core/Media/ImageCombinerOptions.cs +++ b/SnapX.Core/Media/ImageCombinerOptions.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Media/ScreenRecordManager.cs b/SnapX.Core/Media/ScreenRecordManager.cs index 54ae5379c..0c0976854 100644 --- a/SnapX.Core/Media/ScreenRecordManager.cs +++ b/SnapX.Core/Media/ScreenRecordManager.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Media/Screenshot_Transparent.cs b/SnapX.Core/Media/Screenshot_Transparent.cs index 58cf0bd40..b917e1441 100644 --- a/SnapX.Core/Media/Screenshot_Transparent.cs +++ b/SnapX.Core/Media/Screenshot_Transparent.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Media/VideoConverterOptions.cs b/SnapX.Core/Media/VideoConverterOptions.cs index 2c61992a7..a0db5455a 100644 --- a/SnapX.Core/Media/VideoConverterOptions.cs +++ b/SnapX.Core/Media/VideoConverterOptions.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Media/VideoInfo.cs b/SnapX.Core/Media/VideoInfo.cs index 8048dc688..597a1a42a 100644 --- a/SnapX.Core/Media/VideoInfo.cs +++ b/SnapX.Core/Media/VideoInfo.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Media/VideoThumbnailInfo.cs b/SnapX.Core/Media/VideoThumbnailInfo.cs index fab83447b..a07a077b6 100644 --- a/SnapX.Core/Media/VideoThumbnailInfo.cs +++ b/SnapX.Core/Media/VideoThumbnailInfo.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Media/VideoThumbnailOptions.cs b/SnapX.Core/Media/VideoThumbnailOptions.cs index 0af393fcf..d5c822ad3 100644 --- a/SnapX.Core/Media/VideoThumbnailOptions.cs +++ b/SnapX.Core/Media/VideoThumbnailOptions.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Media/VideoThumbnailer.cs b/SnapX.Core/Media/VideoThumbnailer.cs index 3cdd8d4e1..e67faea8b 100644 --- a/SnapX.Core/Media/VideoThumbnailer.cs +++ b/SnapX.Core/Media/VideoThumbnailer.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SettingManager.cs b/SnapX.Core/SettingManager.cs index 252bbc056..d860657ee 100644 --- a/SnapX.Core/SettingManager.cs +++ b/SnapX.Core/SettingManager.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SharpCapture/Animations/BaseAnimation.cs b/SnapX.Core/SharpCapture/Animations/BaseAnimation.cs index 45839a27c..2d777f61f 100644 --- a/SnapX.Core/SharpCapture/Animations/BaseAnimation.cs +++ b/SnapX.Core/SharpCapture/Animations/BaseAnimation.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SharpCapture/Animations/ColorBlinkAnimation.cs b/SnapX.Core/SharpCapture/Animations/ColorBlinkAnimation.cs index aebb91213..d7792bb54 100644 --- a/SnapX.Core/SharpCapture/Animations/ColorBlinkAnimation.cs +++ b/SnapX.Core/SharpCapture/Animations/ColorBlinkAnimation.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SharpCapture/Animations/PointAnimation.cs b/SnapX.Core/SharpCapture/Animations/PointAnimation.cs index a400f2216..e8b322fcf 100644 --- a/SnapX.Core/SharpCapture/Animations/PointAnimation.cs +++ b/SnapX.Core/SharpCapture/Animations/PointAnimation.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SharpCapture/Animations/RectangleAnimation.cs b/SnapX.Core/SharpCapture/Animations/RectangleAnimation.cs index 6fb510e31..d7341f749 100644 --- a/SnapX.Core/SharpCapture/Animations/RectangleAnimation.cs +++ b/SnapX.Core/SharpCapture/Animations/RectangleAnimation.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SharpCapture/Animations/TextAnimation.cs b/SnapX.Core/SharpCapture/Animations/TextAnimation.cs index 924105c3c..f33cede58 100644 --- a/SnapX.Core/SharpCapture/Animations/TextAnimation.cs +++ b/SnapX.Core/SharpCapture/Animations/TextAnimation.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SharpCapture/CaptureActiveMonitor.cs b/SnapX.Core/SharpCapture/CaptureActiveMonitor.cs index fd9cab7d9..4ce65dfb9 100644 --- a/SnapX.Core/SharpCapture/CaptureActiveMonitor.cs +++ b/SnapX.Core/SharpCapture/CaptureActiveMonitor.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SharpCapture/CaptureActiveWindow.cs b/SnapX.Core/SharpCapture/CaptureActiveWindow.cs index 14e2590fe..129806d3b 100644 --- a/SnapX.Core/SharpCapture/CaptureActiveWindow.cs +++ b/SnapX.Core/SharpCapture/CaptureActiveWindow.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SharpCapture/CaptureBase.cs b/SnapX.Core/SharpCapture/CaptureBase.cs index 5a4c98edb..345caa05a 100644 --- a/SnapX.Core/SharpCapture/CaptureBase.cs +++ b/SnapX.Core/SharpCapture/CaptureBase.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SharpCapture/CaptureCustomRegion.cs b/SnapX.Core/SharpCapture/CaptureCustomRegion.cs index abd0aa692..d2e8671f8 100644 --- a/SnapX.Core/SharpCapture/CaptureCustomRegion.cs +++ b/SnapX.Core/SharpCapture/CaptureCustomRegion.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SharpCapture/CaptureCustomWindow.cs b/SnapX.Core/SharpCapture/CaptureCustomWindow.cs index d25720f1b..7d397ba52 100644 --- a/SnapX.Core/SharpCapture/CaptureCustomWindow.cs +++ b/SnapX.Core/SharpCapture/CaptureCustomWindow.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SharpCapture/CaptureFullscreen.cs b/SnapX.Core/SharpCapture/CaptureFullscreen.cs index b41882721..df7b3e51a 100644 --- a/SnapX.Core/SharpCapture/CaptureFullscreen.cs +++ b/SnapX.Core/SharpCapture/CaptureFullscreen.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SharpCapture/CaptureLastRegion.cs b/SnapX.Core/SharpCapture/CaptureLastRegion.cs index 530d24806..9d5bfeeb0 100644 --- a/SnapX.Core/SharpCapture/CaptureLastRegion.cs +++ b/SnapX.Core/SharpCapture/CaptureLastRegion.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SharpCapture/CaptureMonitor.cs b/SnapX.Core/SharpCapture/CaptureMonitor.cs index e3aa69da5..e8a2faba2 100644 --- a/SnapX.Core/SharpCapture/CaptureMonitor.cs +++ b/SnapX.Core/SharpCapture/CaptureMonitor.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SharpCapture/CaptureRegion.cs b/SnapX.Core/SharpCapture/CaptureRegion.cs index 02920c3c3..08741764a 100644 --- a/SnapX.Core/SharpCapture/CaptureRegion.cs +++ b/SnapX.Core/SharpCapture/CaptureRegion.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SharpCapture/CaptureWindow.cs b/SnapX.Core/SharpCapture/CaptureWindow.cs index 78ff2becb..ea4a89a14 100644 --- a/SnapX.Core/SharpCapture/CaptureWindow.cs +++ b/SnapX.Core/SharpCapture/CaptureWindow.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SharpCapture/Enums.cs b/SnapX.Core/SharpCapture/Enums.cs index 39ba38537..17863fa7a 100644 --- a/SnapX.Core/SharpCapture/Enums.cs +++ b/SnapX.Core/SharpCapture/Enums.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SharpCapture/Helpers/InputManager.cs b/SnapX.Core/SharpCapture/Helpers/InputManager.cs index 24628b06d..4a7eccf4c 100644 --- a/SnapX.Core/SharpCapture/Helpers/InputManager.cs +++ b/SnapX.Core/SharpCapture/Helpers/InputManager.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SharpCapture/Helpers/SimpleWindowInfo.cs b/SnapX.Core/SharpCapture/Helpers/SimpleWindowInfo.cs index 3993de98a..937d3aa27 100644 --- a/SnapX.Core/SharpCapture/Helpers/SimpleWindowInfo.cs +++ b/SnapX.Core/SharpCapture/Helpers/SimpleWindowInfo.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SharpCapture/Helpers/SnapSize.cs b/SnapX.Core/SharpCapture/Helpers/SnapSize.cs index 947d685ee..277e662b2 100644 --- a/SnapX.Core/SharpCapture/Helpers/SnapSize.cs +++ b/SnapX.Core/SharpCapture/Helpers/SnapSize.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SharpCapture/RegionCaptureOptions.cs b/SnapX.Core/SharpCapture/RegionCaptureOptions.cs index 34094c5d1..01588b564 100644 --- a/SnapX.Core/SharpCapture/RegionCaptureOptions.cs +++ b/SnapX.Core/SharpCapture/RegionCaptureOptions.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SharpCapture/ScreenRecording/FFmpegCaptureDevice.cs b/SnapX.Core/SharpCapture/ScreenRecording/FFmpegCaptureDevice.cs index c1f14191a..f809f9e73 100644 --- a/SnapX.Core/SharpCapture/ScreenRecording/FFmpegCaptureDevice.cs +++ b/SnapX.Core/SharpCapture/ScreenRecording/FFmpegCaptureDevice.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SharpCapture/ScreenRecording/ImageCache.cs b/SnapX.Core/SharpCapture/ScreenRecording/ImageCache.cs index 22292ced5..9038b0cdb 100644 --- a/SnapX.Core/SharpCapture/ScreenRecording/ImageCache.cs +++ b/SnapX.Core/SharpCapture/ScreenRecording/ImageCache.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SharpCapture/ScreenRecording/ScreenRecorder.cs b/SnapX.Core/SharpCapture/ScreenRecording/ScreenRecorder.cs index 94f0b6c06..e0f807fac 100644 --- a/SnapX.Core/SharpCapture/ScreenRecording/ScreenRecorder.cs +++ b/SnapX.Core/SharpCapture/ScreenRecording/ScreenRecorder.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SharpCapture/ScreenRecording/ScreenRecordingOptions.cs b/SnapX.Core/SharpCapture/ScreenRecording/ScreenRecordingOptions.cs index df835b37e..6dfda361f 100644 --- a/SnapX.Core/SharpCapture/ScreenRecording/ScreenRecordingOptions.cs +++ b/SnapX.Core/SharpCapture/ScreenRecording/ScreenRecordingOptions.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/SnapXResources.cs b/SnapX.Core/SnapXResources.cs index c7d080abe..c47680546 100644 --- a/SnapX.Core/SnapXResources.cs +++ b/SnapX.Core/SnapXResources.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/APIKeys.cs b/SnapX.Core/Upload/APIKeys.cs index afb0f1d42..2190f49ae 100644 --- a/SnapX.Core/Upload/APIKeys.cs +++ b/SnapX.Core/Upload/APIKeys.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/BaseServices/FileUploaderService.cs b/SnapX.Core/Upload/BaseServices/FileUploaderService.cs index c482b71f0..792e09c7a 100644 --- a/SnapX.Core/Upload/BaseServices/FileUploaderService.cs +++ b/SnapX.Core/Upload/BaseServices/FileUploaderService.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/BaseServices/IGenericUploaderService.cs b/SnapX.Core/Upload/BaseServices/IGenericUploaderService.cs index 3a35ccfe1..793b16d0d 100644 --- a/SnapX.Core/Upload/BaseServices/IGenericUploaderService.cs +++ b/SnapX.Core/Upload/BaseServices/IGenericUploaderService.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/BaseServices/IUploaderService.cs b/SnapX.Core/Upload/BaseServices/IUploaderService.cs index 72bc1f37f..6a315d6de 100644 --- a/SnapX.Core/Upload/BaseServices/IUploaderService.cs +++ b/SnapX.Core/Upload/BaseServices/IUploaderService.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/BaseServices/ImageUploaderService.cs b/SnapX.Core/Upload/BaseServices/ImageUploaderService.cs index 2d48d4805..5ce1a44ef 100644 --- a/SnapX.Core/Upload/BaseServices/ImageUploaderService.cs +++ b/SnapX.Core/Upload/BaseServices/ImageUploaderService.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/BaseServices/TextUploaderService.cs b/SnapX.Core/Upload/BaseServices/TextUploaderService.cs index b8d3148e8..5d3455e26 100644 --- a/SnapX.Core/Upload/BaseServices/TextUploaderService.cs +++ b/SnapX.Core/Upload/BaseServices/TextUploaderService.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/BaseServices/URLSharingService.cs b/SnapX.Core/Upload/BaseServices/URLSharingService.cs index 5715c5733..c7bfe506a 100644 --- a/SnapX.Core/Upload/BaseServices/URLSharingService.cs +++ b/SnapX.Core/Upload/BaseServices/URLSharingService.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/BaseServices/URLShortenerService.cs b/SnapX.Core/Upload/BaseServices/URLShortenerService.cs index 2c6e0cb93..f9b5a9212 100644 --- a/SnapX.Core/Upload/BaseServices/URLShortenerService.cs +++ b/SnapX.Core/Upload/BaseServices/URLShortenerService.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/BaseServices/UploaderService.cs b/SnapX.Core/Upload/BaseServices/UploaderService.cs index 20c372f0a..12097be24 100644 --- a/SnapX.Core/Upload/BaseServices/UploaderService.cs +++ b/SnapX.Core/Upload/BaseServices/UploaderService.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/BaseUploaders/GenericUploader.cs b/SnapX.Core/Upload/BaseUploaders/GenericUploader.cs index 67535c588..d154505a5 100644 --- a/SnapX.Core/Upload/BaseUploaders/GenericUploader.cs +++ b/SnapX.Core/Upload/BaseUploaders/GenericUploader.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/BaseUploaders/ImageUploader.cs b/SnapX.Core/Upload/BaseUploaders/ImageUploader.cs index eae6feaf5..a05b02772 100644 --- a/SnapX.Core/Upload/BaseUploaders/ImageUploader.cs +++ b/SnapX.Core/Upload/BaseUploaders/ImageUploader.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/BaseUploaders/TextUploader.cs b/SnapX.Core/Upload/BaseUploaders/TextUploader.cs index f54adbefe..e586908e6 100644 --- a/SnapX.Core/Upload/BaseUploaders/TextUploader.cs +++ b/SnapX.Core/Upload/BaseUploaders/TextUploader.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/BaseUploaders/URLSharer.cs b/SnapX.Core/Upload/BaseUploaders/URLSharer.cs index 90205b4f6..a32d1ed45 100644 --- a/SnapX.Core/Upload/BaseUploaders/URLSharer.cs +++ b/SnapX.Core/Upload/BaseUploaders/URLSharer.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/BaseUploaders/URLShortener.cs b/SnapX.Core/Upload/BaseUploaders/URLShortener.cs index 745c00089..b59ece41f 100644 --- a/SnapX.Core/Upload/BaseUploaders/URLShortener.cs +++ b/SnapX.Core/Upload/BaseUploaders/URLShortener.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/BaseUploaders/Uploader.cs b/SnapX.Core/Upload/BaseUploaders/Uploader.cs index 298c32ce7..f136177cf 100644 --- a/SnapX.Core/Upload/BaseUploaders/Uploader.cs +++ b/SnapX.Core/Upload/BaseUploaders/Uploader.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Custom/CustomUploaderInput.cs b/SnapX.Core/Upload/Custom/CustomUploaderInput.cs index 2617f340d..f4bef15c3 100644 --- a/SnapX.Core/Upload/Custom/CustomUploaderInput.cs +++ b/SnapX.Core/Upload/Custom/CustomUploaderInput.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Custom/CustomUploaderItem.cs b/SnapX.Core/Upload/Custom/CustomUploaderItem.cs index 1b9413d1c..061ab0ad2 100644 --- a/SnapX.Core/Upload/Custom/CustomUploaderItem.cs +++ b/SnapX.Core/Upload/Custom/CustomUploaderItem.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunction.cs b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunction.cs index 124527530..ce9d2bb2a 100644 --- a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunction.cs +++ b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunction.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionBase64.cs b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionBase64.cs index 0aa624e91..35d702b07 100644 --- a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionBase64.cs +++ b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionBase64.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionFileName.cs b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionFileName.cs index 8a9b486a6..bca367219 100644 --- a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionFileName.cs +++ b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionFileName.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionHeader.cs b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionHeader.cs index a11b2ed31..423109ea4 100644 --- a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionHeader.cs +++ b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionHeader.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionInput.cs b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionInput.cs index dabc7a685..ec4f26a78 100644 --- a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionInput.cs +++ b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionInput.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionInputBox.cs b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionInputBox.cs index 8e4fb1ce3..920b0f4fa 100644 --- a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionInputBox.cs +++ b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionInputBox.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionJson.cs b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionJson.cs index 6b1cfffac..aa01a23bd 100644 --- a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionJson.cs +++ b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionJson.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionOutputBox.cs b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionOutputBox.cs index f1a1f4d54..c136b9d59 100644 --- a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionOutputBox.cs +++ b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionOutputBox.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionRandom.cs b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionRandom.cs index 7e2c88651..6fd64b676 100644 --- a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionRandom.cs +++ b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionRandom.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionRegex.cs b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionRegex.cs index 63718675c..11dbcfb5e 100644 --- a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionRegex.cs +++ b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionRegex.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionResponse.cs b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionResponse.cs index b8b16f32a..4c4071fe5 100644 --- a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionResponse.cs +++ b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionResponse.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionResponseURL.cs b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionResponseURL.cs index 40462401c..c9e0944d9 100644 --- a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionResponseURL.cs +++ b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionResponseURL.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionSelect.cs b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionSelect.cs index 96c783636..82c01ceef 100644 --- a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionSelect.cs +++ b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionSelect.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionXml.cs b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionXml.cs index abe22c9be..2bf1701a5 100644 --- a/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionXml.cs +++ b/SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionXml.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Custom/ShareXCustomUploaderSyntaxParser.cs b/SnapX.Core/Upload/Custom/ShareXCustomUploaderSyntaxParser.cs index 3d71e66fb..5cf4b17b4 100644 --- a/SnapX.Core/Upload/Custom/ShareXCustomUploaderSyntaxParser.cs +++ b/SnapX.Core/Upload/Custom/ShareXCustomUploaderSyntaxParser.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Custom/ShareXSyntaxParser.cs b/SnapX.Core/Upload/Custom/ShareXSyntaxParser.cs index 7407eaaa9..28a4928a7 100644 --- a/SnapX.Core/Upload/Custom/ShareXSyntaxParser.cs +++ b/SnapX.Core/Upload/Custom/ShareXSyntaxParser.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/AmazonS3.cs b/SnapX.Core/Upload/File/AmazonS3.cs index 4f1c37ecd..f5fe5f91d 100644 --- a/SnapX.Core/Upload/File/AmazonS3.cs +++ b/SnapX.Core/Upload/File/AmazonS3.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/AmazonS3Endpoint.cs b/SnapX.Core/Upload/File/AmazonS3Endpoint.cs index dfb949707..2c1c644aa 100644 --- a/SnapX.Core/Upload/File/AmazonS3Endpoint.cs +++ b/SnapX.Core/Upload/File/AmazonS3Endpoint.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/AmazonS3Settings.cs b/SnapX.Core/Upload/File/AmazonS3Settings.cs index 542a5c442..397778724 100644 --- a/SnapX.Core/Upload/File/AmazonS3Settings.cs +++ b/SnapX.Core/Upload/File/AmazonS3Settings.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/AzureStorage.cs b/SnapX.Core/Upload/File/AzureStorage.cs index e934fc58a..62141f9ea 100644 --- a/SnapX.Core/Upload/File/AzureStorage.cs +++ b/SnapX.Core/Upload/File/AzureStorage.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/BackblazeB2.cs b/SnapX.Core/Upload/File/BackblazeB2.cs index 9ad977fa9..d69a5b955 100644 --- a/SnapX.Core/Upload/File/BackblazeB2.cs +++ b/SnapX.Core/Upload/File/BackblazeB2.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/Box.cs b/SnapX.Core/Upload/File/Box.cs index 5bf3a8275..b20a59da5 100644 --- a/SnapX.Core/Upload/File/Box.cs +++ b/SnapX.Core/Upload/File/Box.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/Copy.cs b/SnapX.Core/Upload/File/Copy.cs index 495bb9901..dd741dec6 100644 --- a/SnapX.Core/Upload/File/Copy.cs +++ b/SnapX.Core/Upload/File/Copy.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/CustomFileUploader.cs b/SnapX.Core/Upload/File/CustomFileUploader.cs index ffb236698..1f255bb4f 100644 --- a/SnapX.Core/Upload/File/CustomFileUploader.cs +++ b/SnapX.Core/Upload/File/CustomFileUploader.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/DropIO.cs b/SnapX.Core/Upload/File/DropIO.cs index d71652814..3c9bafd05 100644 --- a/SnapX.Core/Upload/File/DropIO.cs +++ b/SnapX.Core/Upload/File/DropIO.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/Dropbox.cs b/SnapX.Core/Upload/File/Dropbox.cs index e2cf1b641..e55c04dca 100644 --- a/SnapX.Core/Upload/File/Dropbox.cs +++ b/SnapX.Core/Upload/File/Dropbox.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/Email.cs b/SnapX.Core/Upload/File/Email.cs index 5bc29c660..43a73b0bc 100644 --- a/SnapX.Core/Upload/File/Email.cs +++ b/SnapX.Core/Upload/File/Email.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/FTP.cs b/SnapX.Core/Upload/File/FTP.cs index 22d022688..5343bc553 100644 --- a/SnapX.Core/Upload/File/FTP.cs +++ b/SnapX.Core/Upload/File/FTP.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/FTPAccount.cs b/SnapX.Core/Upload/File/FTPAccount.cs index e3a8b2fd5..b64867695 100644 --- a/SnapX.Core/Upload/File/FTPAccount.cs +++ b/SnapX.Core/Upload/File/FTPAccount.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/FileBin.cs b/SnapX.Core/Upload/File/FileBin.cs index e78e54fa3..c9abbf8cb 100644 --- a/SnapX.Core/Upload/File/FileBin.cs +++ b/SnapX.Core/Upload/File/FileBin.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/FileSonic.cs b/SnapX.Core/Upload/File/FileSonic.cs index 608df1ac1..64c97fbf8 100644 --- a/SnapX.Core/Upload/File/FileSonic.cs +++ b/SnapX.Core/Upload/File/FileSonic.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/GoogleCloudStorage.cs b/SnapX.Core/Upload/File/GoogleCloudStorage.cs index f1788a488..84bf5733a 100644 --- a/SnapX.Core/Upload/File/GoogleCloudStorage.cs +++ b/SnapX.Core/Upload/File/GoogleCloudStorage.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/GoogleDrive.cs b/SnapX.Core/Upload/File/GoogleDrive.cs index 2ffce4649..72801cf26 100644 --- a/SnapX.Core/Upload/File/GoogleDrive.cs +++ b/SnapX.Core/Upload/File/GoogleDrive.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/Hostr.cs b/SnapX.Core/Upload/File/Hostr.cs index 0c0c67b66..0502fdc6e 100644 --- a/SnapX.Core/Upload/File/Hostr.cs +++ b/SnapX.Core/Upload/File/Hostr.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/Jira.cs b/SnapX.Core/Upload/File/Jira.cs index e91ab0c3b..cd29a2fea 100644 --- a/SnapX.Core/Upload/File/Jira.cs +++ b/SnapX.Core/Upload/File/Jira.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/Lambda.cs b/SnapX.Core/Upload/File/Lambda.cs index 21c5be97a..3255ab245 100644 --- a/SnapX.Core/Upload/File/Lambda.cs +++ b/SnapX.Core/Upload/File/Lambda.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/LobFile.cs b/SnapX.Core/Upload/File/LobFile.cs index 43ecdf632..479eba7c2 100644 --- a/SnapX.Core/Upload/File/LobFile.cs +++ b/SnapX.Core/Upload/File/LobFile.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/LocalhostAccount.cs b/SnapX.Core/Upload/File/LocalhostAccount.cs index 3d3049180..84469cf05 100644 --- a/SnapX.Core/Upload/File/LocalhostAccount.cs +++ b/SnapX.Core/Upload/File/LocalhostAccount.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/MediaFire.cs b/SnapX.Core/Upload/File/MediaFire.cs index 193db5ac5..c2bbdb1fd 100644 --- a/SnapX.Core/Upload/File/MediaFire.cs +++ b/SnapX.Core/Upload/File/MediaFire.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/Mega.cs b/SnapX.Core/Upload/File/Mega.cs index 54a051138..0086b85c5 100644 --- a/SnapX.Core/Upload/File/Mega.cs +++ b/SnapX.Core/Upload/File/Mega.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/MegaAuthInfos.cs b/SnapX.Core/Upload/File/MegaAuthInfos.cs index 83094a402..9f473d22c 100644 --- a/SnapX.Core/Upload/File/MegaAuthInfos.cs +++ b/SnapX.Core/Upload/File/MegaAuthInfos.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/OneDrive.cs b/SnapX.Core/Upload/File/OneDrive.cs index b4f5f4d89..64003e3f6 100644 --- a/SnapX.Core/Upload/File/OneDrive.cs +++ b/SnapX.Core/Upload/File/OneDrive.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/OwnCloud.cs b/SnapX.Core/Upload/File/OwnCloud.cs index 34f43bddf..69fe5b56b 100644 --- a/SnapX.Core/Upload/File/OwnCloud.cs +++ b/SnapX.Core/Upload/File/OwnCloud.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/Plik.cs b/SnapX.Core/Upload/File/Plik.cs index b8820c3ec..f80976e64 100644 --- a/SnapX.Core/Upload/File/Plik.cs +++ b/SnapX.Core/Upload/File/Plik.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/PlikSettings.cs b/SnapX.Core/Upload/File/PlikSettings.cs index 304d1d72c..0e8b30fb3 100644 --- a/SnapX.Core/Upload/File/PlikSettings.cs +++ b/SnapX.Core/Upload/File/PlikSettings.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/Pomf.cs b/SnapX.Core/Upload/File/Pomf.cs index b040cc5e0..707950052 100644 --- a/SnapX.Core/Upload/File/Pomf.cs +++ b/SnapX.Core/Upload/File/Pomf.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/PomfUploader.cs b/SnapX.Core/Upload/File/PomfUploader.cs index 6b6b851a2..9eff96338 100644 --- a/SnapX.Core/Upload/File/PomfUploader.cs +++ b/SnapX.Core/Upload/File/PomfUploader.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/Pushbullet.cs b/SnapX.Core/Upload/File/Pushbullet.cs index 067958d7d..5d2fafa1b 100644 --- a/SnapX.Core/Upload/File/Pushbullet.cs +++ b/SnapX.Core/Upload/File/Pushbullet.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/Puush.cs b/SnapX.Core/Upload/File/Puush.cs index a2e233130..f9ba45941 100644 --- a/SnapX.Core/Upload/File/Puush.cs +++ b/SnapX.Core/Upload/File/Puush.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/SFTP.cs b/SnapX.Core/Upload/File/SFTP.cs index 60d06ee76..f186c035a 100644 --- a/SnapX.Core/Upload/File/SFTP.cs +++ b/SnapX.Core/Upload/File/SFTP.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/Seafile.cs b/SnapX.Core/Upload/File/Seafile.cs index 369f78bcc..074dc4fc4 100644 --- a/SnapX.Core/Upload/File/Seafile.cs +++ b/SnapX.Core/Upload/File/Seafile.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/SendSpace.cs b/SnapX.Core/Upload/File/SendSpace.cs index ecdedc38b..35ab45537 100644 --- a/SnapX.Core/Upload/File/SendSpace.cs +++ b/SnapX.Core/Upload/File/SendSpace.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/SendSpaceManager.cs b/SnapX.Core/Upload/File/SendSpaceManager.cs index f2aef5936..4d577b2f5 100644 --- a/SnapX.Core/Upload/File/SendSpaceManager.cs +++ b/SnapX.Core/Upload/File/SendSpaceManager.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/ShareCX.cs b/SnapX.Core/Upload/File/ShareCX.cs index 5f6a13f6e..78f1b704d 100644 --- a/SnapX.Core/Upload/File/ShareCX.cs +++ b/SnapX.Core/Upload/File/ShareCX.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/SharedFolderUploader.cs b/SnapX.Core/Upload/File/SharedFolderUploader.cs index cef89855c..024e77cdd 100644 --- a/SnapX.Core/Upload/File/SharedFolderUploader.cs +++ b/SnapX.Core/Upload/File/SharedFolderUploader.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/Streamable.cs b/SnapX.Core/Upload/File/Streamable.cs index 5230ac86f..0e9d636b8 100644 --- a/SnapX.Core/Upload/File/Streamable.cs +++ b/SnapX.Core/Upload/File/Streamable.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/Sul.cs b/SnapX.Core/Upload/File/Sul.cs index 4f38a675c..2d996dfe9 100644 --- a/SnapX.Core/Upload/File/Sul.cs +++ b/SnapX.Core/Upload/File/Sul.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/Transfersh.cs b/SnapX.Core/Upload/File/Transfersh.cs index 5301aa842..b21dade6f 100644 --- a/SnapX.Core/Upload/File/Transfersh.cs +++ b/SnapX.Core/Upload/File/Transfersh.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/Uguu.cs b/SnapX.Core/Upload/File/Uguu.cs index baa4e1197..4159c78de 100644 --- a/SnapX.Core/Upload/File/Uguu.cs +++ b/SnapX.Core/Upload/File/Uguu.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/Vault_ooo.cs b/SnapX.Core/Upload/File/Vault_ooo.cs index d859bde4e..e977dafa5 100644 --- a/SnapX.Core/Upload/File/Vault_ooo.cs +++ b/SnapX.Core/Upload/File/Vault_ooo.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/File/YouTube.cs b/SnapX.Core/Upload/File/YouTube.cs index d8411095f..b60909903 100644 --- a/SnapX.Core/Upload/File/YouTube.cs +++ b/SnapX.Core/Upload/File/YouTube.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Img/Chevereto.cs b/SnapX.Core/Upload/Img/Chevereto.cs index fc51fce04..eed164a20 100644 --- a/SnapX.Core/Upload/Img/Chevereto.cs +++ b/SnapX.Core/Upload/Img/Chevereto.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Img/CheveretoUploader.cs b/SnapX.Core/Upload/Img/CheveretoUploader.cs index 962325fb0..67e65145d 100644 --- a/SnapX.Core/Upload/Img/CheveretoUploader.cs +++ b/SnapX.Core/Upload/Img/CheveretoUploader.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Img/CustomImageUploader.cs b/SnapX.Core/Upload/Img/CustomImageUploader.cs index 959de309e..b44fd60fa 100644 --- a/SnapX.Core/Upload/Img/CustomImageUploader.cs +++ b/SnapX.Core/Upload/Img/CustomImageUploader.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Img/FlickrUploader.cs b/SnapX.Core/Upload/Img/FlickrUploader.cs index c755e8266..a860f2530 100644 --- a/SnapX.Core/Upload/Img/FlickrUploader.cs +++ b/SnapX.Core/Upload/Img/FlickrUploader.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Img/ImageBin.cs b/SnapX.Core/Upload/Img/ImageBin.cs index 3192fabf5..62f042d99 100644 --- a/SnapX.Core/Upload/Img/ImageBin.cs +++ b/SnapX.Core/Upload/Img/ImageBin.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Img/ImageShackUploader.cs b/SnapX.Core/Upload/Img/ImageShackUploader.cs index 19e94029a..7f4a31164 100644 --- a/SnapX.Core/Upload/Img/ImageShackUploader.cs +++ b/SnapX.Core/Upload/Img/ImageShackUploader.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Img/Img1Uploader.cs b/SnapX.Core/Upload/Img/Img1Uploader.cs index 7f05556b2..1aa73cd9c 100644 --- a/SnapX.Core/Upload/Img/Img1Uploader.cs +++ b/SnapX.Core/Upload/Img/Img1Uploader.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Img/Imgur.cs b/SnapX.Core/Upload/Img/Imgur.cs index 591e6d5ec..c2db2f0c6 100644 --- a/SnapX.Core/Upload/Img/Imgur.cs +++ b/SnapX.Core/Upload/Img/Imgur.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Img/ImmioUploader.cs b/SnapX.Core/Upload/Img/ImmioUploader.cs index 42b8ed383..86b62981b 100644 --- a/SnapX.Core/Upload/Img/ImmioUploader.cs +++ b/SnapX.Core/Upload/Img/ImmioUploader.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Img/Photobucket.cs b/SnapX.Core/Upload/Img/Photobucket.cs index f48014f7a..5762a8b55 100644 --- a/SnapX.Core/Upload/Img/Photobucket.cs +++ b/SnapX.Core/Upload/Img/Photobucket.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Img/TwitPicUploader.cs b/SnapX.Core/Upload/Img/TwitPicUploader.cs index 1b0431aa0..065e72653 100644 --- a/SnapX.Core/Upload/Img/TwitPicUploader.cs +++ b/SnapX.Core/Upload/Img/TwitPicUploader.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Img/TwitSnapsUploader.cs b/SnapX.Core/Upload/Img/TwitSnapsUploader.cs index c3060a06e..eba820e64 100644 --- a/SnapX.Core/Upload/Img/TwitSnapsUploader.cs +++ b/SnapX.Core/Upload/Img/TwitSnapsUploader.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Img/Twitter.cs b/SnapX.Core/Upload/Img/Twitter.cs index b4978bfe7..affbc70ed 100644 --- a/SnapX.Core/Upload/Img/Twitter.cs +++ b/SnapX.Core/Upload/Img/Twitter.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Img/UploadScreenshot.cs b/SnapX.Core/Upload/Img/UploadScreenshot.cs index 29047cae8..7ac985524 100644 --- a/SnapX.Core/Upload/Img/UploadScreenshot.cs +++ b/SnapX.Core/Upload/Img/UploadScreenshot.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Img/VgymeUploader.cs b/SnapX.Core/Upload/Img/VgymeUploader.cs index cd4ca8ef4..5d77f0c9e 100644 --- a/SnapX.Core/Upload/Img/VgymeUploader.cs +++ b/SnapX.Core/Upload/Img/VgymeUploader.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Img/YfrogUploader.cs b/SnapX.Core/Upload/Img/YfrogUploader.cs index 5231821b5..09db7f885 100644 --- a/SnapX.Core/Upload/Img/YfrogUploader.cs +++ b/SnapX.Core/Upload/Img/YfrogUploader.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/OAuth/GoogleOAuth2.cs b/SnapX.Core/Upload/OAuth/GoogleOAuth2.cs index b3af891eb..413a3cfbc 100644 --- a/SnapX.Core/Upload/OAuth/GoogleOAuth2.cs +++ b/SnapX.Core/Upload/OAuth/GoogleOAuth2.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/OAuth/IOAuth.cs b/SnapX.Core/Upload/OAuth/IOAuth.cs index caf0996e8..be7d71422 100644 --- a/SnapX.Core/Upload/OAuth/IOAuth.cs +++ b/SnapX.Core/Upload/OAuth/IOAuth.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/OAuth/IOAuth2.cs b/SnapX.Core/Upload/OAuth/IOAuth2.cs index 40f9d9423..e419f23dc 100644 --- a/SnapX.Core/Upload/OAuth/IOAuth2.cs +++ b/SnapX.Core/Upload/OAuth/IOAuth2.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/OAuth/IOAuth2Basic.cs b/SnapX.Core/Upload/OAuth/IOAuth2Basic.cs index e1f27f4a0..73aa121dd 100644 --- a/SnapX.Core/Upload/OAuth/IOAuth2Basic.cs +++ b/SnapX.Core/Upload/OAuth/IOAuth2Basic.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/OAuth/IOAuthBase.cs b/SnapX.Core/Upload/OAuth/IOAuthBase.cs index 1bd0a3bb0..91ca502e8 100644 --- a/SnapX.Core/Upload/OAuth/IOAuthBase.cs +++ b/SnapX.Core/Upload/OAuth/IOAuthBase.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/OAuth/IOauth2Loopback.cs b/SnapX.Core/Upload/OAuth/IOauth2Loopback.cs index 81a421d7b..223479434 100644 --- a/SnapX.Core/Upload/OAuth/IOauth2Loopback.cs +++ b/SnapX.Core/Upload/OAuth/IOauth2Loopback.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/OAuth/OAuth2Info.cs b/SnapX.Core/Upload/OAuth/OAuth2Info.cs index d1e3eadef..1fd8a1ea0 100644 --- a/SnapX.Core/Upload/OAuth/OAuth2Info.cs +++ b/SnapX.Core/Upload/OAuth/OAuth2Info.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/OAuth/OAuth2ProofKey.cs b/SnapX.Core/Upload/OAuth/OAuth2ProofKey.cs index 7e01fe9d6..7592f2af4 100644 --- a/SnapX.Core/Upload/OAuth/OAuth2ProofKey.cs +++ b/SnapX.Core/Upload/OAuth/OAuth2ProofKey.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/OAuth/OAuth2Token.cs b/SnapX.Core/Upload/OAuth/OAuth2Token.cs index 318a021c4..6bf27b9d1 100644 --- a/SnapX.Core/Upload/OAuth/OAuth2Token.cs +++ b/SnapX.Core/Upload/OAuth/OAuth2Token.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/OAuth/OAuthInfo.cs b/SnapX.Core/Upload/OAuth/OAuthInfo.cs index e872a3656..3b824e88e 100644 --- a/SnapX.Core/Upload/OAuth/OAuthInfo.cs +++ b/SnapX.Core/Upload/OAuth/OAuthInfo.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/OAuth/OAuthListener.cs b/SnapX.Core/Upload/OAuth/OAuthListener.cs index 265b3e433..65a57fcc5 100644 --- a/SnapX.Core/Upload/OAuth/OAuthListener.cs +++ b/SnapX.Core/Upload/OAuth/OAuthListener.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/OAuth/OAuthManager.cs b/SnapX.Core/Upload/OAuth/OAuthManager.cs index bc13ead7b..8fbb66375 100644 --- a/SnapX.Core/Upload/OAuth/OAuthManager.cs +++ b/SnapX.Core/Upload/OAuth/OAuthManager.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/OAuth/OAuthUserInfo.cs b/SnapX.Core/Upload/OAuth/OAuthUserInfo.cs index 10f1246f4..c4d5a07ef 100644 --- a/SnapX.Core/Upload/OAuth/OAuthUserInfo.cs +++ b/SnapX.Core/Upload/OAuth/OAuthUserInfo.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/SharingServices/BingVisualSearchSharingService.cs b/SnapX.Core/Upload/SharingServices/BingVisualSearchSharingService.cs index 01d4cd2cf..e67882fb9 100644 --- a/SnapX.Core/Upload/SharingServices/BingVisualSearchSharingService.cs +++ b/SnapX.Core/Upload/SharingServices/BingVisualSearchSharingService.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/SharingServices/CustomURLSharingService.cs b/SnapX.Core/Upload/SharingServices/CustomURLSharingService.cs index 84bbaa955..bf650a936 100644 --- a/SnapX.Core/Upload/SharingServices/CustomURLSharingService.cs +++ b/SnapX.Core/Upload/SharingServices/CustomURLSharingService.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/SharingServices/DeliciousSharingService.cs b/SnapX.Core/Upload/SharingServices/DeliciousSharingService.cs index 415831fa8..ec7222cf8 100644 --- a/SnapX.Core/Upload/SharingServices/DeliciousSharingService.cs +++ b/SnapX.Core/Upload/SharingServices/DeliciousSharingService.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/SharingServices/EmailSharingService.cs b/SnapX.Core/Upload/SharingServices/EmailSharingService.cs index 0155073a0..99b106bc5 100644 --- a/SnapX.Core/Upload/SharingServices/EmailSharingService.cs +++ b/SnapX.Core/Upload/SharingServices/EmailSharingService.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/SharingServices/FacebookSharingService.cs b/SnapX.Core/Upload/SharingServices/FacebookSharingService.cs index f4a58be39..6637ce52e 100644 --- a/SnapX.Core/Upload/SharingServices/FacebookSharingService.cs +++ b/SnapX.Core/Upload/SharingServices/FacebookSharingService.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/SharingServices/GoogleLensSharingService.cs b/SnapX.Core/Upload/SharingServices/GoogleLensSharingService.cs index 80bcc8a73..b0580693c 100644 --- a/SnapX.Core/Upload/SharingServices/GoogleLensSharingService.cs +++ b/SnapX.Core/Upload/SharingServices/GoogleLensSharingService.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/SharingServices/LinkedInSharingService.cs b/SnapX.Core/Upload/SharingServices/LinkedInSharingService.cs index 43d268393..636ab1d37 100644 --- a/SnapX.Core/Upload/SharingServices/LinkedInSharingService.cs +++ b/SnapX.Core/Upload/SharingServices/LinkedInSharingService.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/SharingServices/PinterestSharingService.cs b/SnapX.Core/Upload/SharingServices/PinterestSharingService.cs index 7e1a0aebe..11bd50235 100644 --- a/SnapX.Core/Upload/SharingServices/PinterestSharingService.cs +++ b/SnapX.Core/Upload/SharingServices/PinterestSharingService.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/SharingServices/PushbulletSharingService.cs b/SnapX.Core/Upload/SharingServices/PushbulletSharingService.cs index 040e6c752..48b64e9ff 100644 --- a/SnapX.Core/Upload/SharingServices/PushbulletSharingService.cs +++ b/SnapX.Core/Upload/SharingServices/PushbulletSharingService.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/SharingServices/RedditSharingService.cs b/SnapX.Core/Upload/SharingServices/RedditSharingService.cs index ec20c0989..5c774a622 100644 --- a/SnapX.Core/Upload/SharingServices/RedditSharingService.cs +++ b/SnapX.Core/Upload/SharingServices/RedditSharingService.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/SharingServices/SimpleURLSharingService.cs b/SnapX.Core/Upload/SharingServices/SimpleURLSharingService.cs index 7f93bf687..553e2f6ae 100644 --- a/SnapX.Core/Upload/SharingServices/SimpleURLSharingService.cs +++ b/SnapX.Core/Upload/SharingServices/SimpleURLSharingService.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/SharingServices/StumbleUponSharingService.cs b/SnapX.Core/Upload/SharingServices/StumbleUponSharingService.cs index f33f98d10..fbc5175a0 100644 --- a/SnapX.Core/Upload/SharingServices/StumbleUponSharingService.cs +++ b/SnapX.Core/Upload/SharingServices/StumbleUponSharingService.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/SharingServices/TumblrSharingService.cs b/SnapX.Core/Upload/SharingServices/TumblrSharingService.cs index a6ca77256..43f5557ca 100644 --- a/SnapX.Core/Upload/SharingServices/TumblrSharingService.cs +++ b/SnapX.Core/Upload/SharingServices/TumblrSharingService.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/SharingServices/TwitterSharingService.cs b/SnapX.Core/Upload/SharingServices/TwitterSharingService.cs index 3f572e628..cd56c2cd8 100644 --- a/SnapX.Core/Upload/SharingServices/TwitterSharingService.cs +++ b/SnapX.Core/Upload/SharingServices/TwitterSharingService.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/SharingServices/VkSharingService.cs b/SnapX.Core/Upload/SharingServices/VkSharingService.cs index b666d2477..3c757b4d8 100644 --- a/SnapX.Core/Upload/SharingServices/VkSharingService.cs +++ b/SnapX.Core/Upload/SharingServices/VkSharingService.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Text/CustomTextUploader.cs b/SnapX.Core/Upload/Text/CustomTextUploader.cs index 69cc5b50e..9bca8f8a3 100644 --- a/SnapX.Core/Upload/Text/CustomTextUploader.cs +++ b/SnapX.Core/Upload/Text/CustomTextUploader.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Text/GitHubGist.cs b/SnapX.Core/Upload/Text/GitHubGist.cs index 44fd40eb4..69851caed 100644 --- a/SnapX.Core/Upload/Text/GitHubGist.cs +++ b/SnapX.Core/Upload/Text/GitHubGist.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Text/Hastebin.cs b/SnapX.Core/Upload/Text/Hastebin.cs index 0a41b3591..e1bfc467c 100644 --- a/SnapX.Core/Upload/Text/Hastebin.cs +++ b/SnapX.Core/Upload/Text/Hastebin.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Text/OneTimeSecret.cs b/SnapX.Core/Upload/Text/OneTimeSecret.cs index f67d65b3c..db0c9fece 100644 --- a/SnapX.Core/Upload/Text/OneTimeSecret.cs +++ b/SnapX.Core/Upload/Text/OneTimeSecret.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Text/Paste2.cs b/SnapX.Core/Upload/Text/Paste2.cs index a621c8ab1..84aeadaac 100644 --- a/SnapX.Core/Upload/Text/Paste2.cs +++ b/SnapX.Core/Upload/Text/Paste2.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Text/Paste_ee.cs b/SnapX.Core/Upload/Text/Paste_ee.cs index 3ec4eef7f..6c3b749c9 100644 --- a/SnapX.Core/Upload/Text/Paste_ee.cs +++ b/SnapX.Core/Upload/Text/Paste_ee.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Text/Pastebin.cs b/SnapX.Core/Upload/Text/Pastebin.cs index df5f8b175..38973a515 100644 --- a/SnapX.Core/Upload/Text/Pastebin.cs +++ b/SnapX.Core/Upload/Text/Pastebin.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Text/Pastebin_ca.cs b/SnapX.Core/Upload/Text/Pastebin_ca.cs index f0af2c3e8..91ed4a5ce 100644 --- a/SnapX.Core/Upload/Text/Pastebin_ca.cs +++ b/SnapX.Core/Upload/Text/Pastebin_ca.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Text/Pastie.cs b/SnapX.Core/Upload/Text/Pastie.cs index b7638dacc..cd06fd7f2 100644 --- a/SnapX.Core/Upload/Text/Pastie.cs +++ b/SnapX.Core/Upload/Text/Pastie.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Text/Slexy.cs b/SnapX.Core/Upload/Text/Slexy.cs index 33481740c..a26074dc5 100644 --- a/SnapX.Core/Upload/Text/Slexy.cs +++ b/SnapX.Core/Upload/Text/Slexy.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Text/Upaste.cs b/SnapX.Core/Upload/Text/Upaste.cs index 2dcb3e8bb..6199c9110 100644 --- a/SnapX.Core/Upload/Text/Upaste.cs +++ b/SnapX.Core/Upload/Text/Upaste.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/URL/BitlyURLShortener.cs b/SnapX.Core/Upload/URL/BitlyURLShortener.cs index e176b4233..b92bf0fa3 100644 --- a/SnapX.Core/Upload/URL/BitlyURLShortener.cs +++ b/SnapX.Core/Upload/URL/BitlyURLShortener.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/URL/CustomURLShortener.cs b/SnapX.Core/Upload/URL/CustomURLShortener.cs index 5e5755cc0..d2a1b1fdf 100644 --- a/SnapX.Core/Upload/URL/CustomURLShortener.cs +++ b/SnapX.Core/Upload/URL/CustomURLShortener.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/URL/FirebaseDynamicLinksURLShortener.cs b/SnapX.Core/Upload/URL/FirebaseDynamicLinksURLShortener.cs index dcacb1eb4..201b107dd 100644 --- a/SnapX.Core/Upload/URL/FirebaseDynamicLinksURLShortener.cs +++ b/SnapX.Core/Upload/URL/FirebaseDynamicLinksURLShortener.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/URL/IsgdURLShortener.cs b/SnapX.Core/Upload/URL/IsgdURLShortener.cs index a76e5a884..f0c3719ac 100644 --- a/SnapX.Core/Upload/URL/IsgdURLShortener.cs +++ b/SnapX.Core/Upload/URL/IsgdURLShortener.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/URL/KuttURLShortener.cs b/SnapX.Core/Upload/URL/KuttURLShortener.cs index 58cb636d8..2a0cbcfc8 100644 --- a/SnapX.Core/Upload/URL/KuttURLShortener.cs +++ b/SnapX.Core/Upload/URL/KuttURLShortener.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/URL/NlcmURLShortener.cs b/SnapX.Core/Upload/URL/NlcmURLShortener.cs index 36e0ef190..94747ebe3 100644 --- a/SnapX.Core/Upload/URL/NlcmURLShortener.cs +++ b/SnapX.Core/Upload/URL/NlcmURLShortener.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/URL/PolrURLShortener.cs b/SnapX.Core/Upload/URL/PolrURLShortener.cs index b83be2f43..1fb928129 100644 --- a/SnapX.Core/Upload/URL/PolrURLShortener.cs +++ b/SnapX.Core/Upload/URL/PolrURLShortener.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/URL/QRnetURLShortener.cs b/SnapX.Core/Upload/URL/QRnetURLShortener.cs index 020c24d9b..4ec537265 100644 --- a/SnapX.Core/Upload/URL/QRnetURLShortener.cs +++ b/SnapX.Core/Upload/URL/QRnetURLShortener.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/URL/TinyURLShortener.cs b/SnapX.Core/Upload/URL/TinyURLShortener.cs index 20338434a..b094e38c8 100644 --- a/SnapX.Core/Upload/URL/TinyURLShortener.cs +++ b/SnapX.Core/Upload/URL/TinyURLShortener.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/URL/TurlURLShortener.cs b/SnapX.Core/Upload/URL/TurlURLShortener.cs index a8c2df575..240b5021f 100644 --- a/SnapX.Core/Upload/URL/TurlURLShortener.cs +++ b/SnapX.Core/Upload/URL/TurlURLShortener.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/URL/TwoGPURLShortener.cs b/SnapX.Core/Upload/URL/TwoGPURLShortener.cs index a971d5b9f..4077e3136 100644 --- a/SnapX.Core/Upload/URL/TwoGPURLShortener.cs +++ b/SnapX.Core/Upload/URL/TwoGPURLShortener.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/URL/VURLShortener.cs b/SnapX.Core/Upload/URL/VURLShortener.cs index 72fee0c7c..c92b2dac3 100644 --- a/SnapX.Core/Upload/URL/VURLShortener.cs +++ b/SnapX.Core/Upload/URL/VURLShortener.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/URL/VgdURLShortener.cs b/SnapX.Core/Upload/URL/VgdURLShortener.cs index 19339f5bf..884d54a77 100644 --- a/SnapX.Core/Upload/URL/VgdURLShortener.cs +++ b/SnapX.Core/Upload/URL/VgdURLShortener.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/URL/YourlsURLShortener.cs b/SnapX.Core/Upload/URL/YourlsURLShortener.cs index 235d74247..d9d0fcb40 100644 --- a/SnapX.Core/Upload/URL/YourlsURLShortener.cs +++ b/SnapX.Core/Upload/URL/YourlsURLShortener.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/URL/ZeroWidthURLShortener.cs b/SnapX.Core/Upload/URL/ZeroWidthURLShortener.cs index e1f04e9a7..887e18aa1 100644 --- a/SnapX.Core/Upload/URL/ZeroWidthURLShortener.cs +++ b/SnapX.Core/Upload/URL/ZeroWidthURLShortener.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/UploadInfoManager.cs b/SnapX.Core/Upload/UploadInfoManager.cs index 7b766caba..0da68edca 100644 --- a/SnapX.Core/Upload/UploadInfoManager.cs +++ b/SnapX.Core/Upload/UploadInfoManager.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/UploadInfoParser.cs b/SnapX.Core/Upload/UploadInfoParser.cs index 616e489f2..2228cd775 100644 --- a/SnapX.Core/Upload/UploadInfoParser.cs +++ b/SnapX.Core/Upload/UploadInfoParser.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/UploadInfoStatus.cs b/SnapX.Core/Upload/UploadInfoStatus.cs index d4d1c5659..c40227bc8 100644 --- a/SnapX.Core/Upload/UploadInfoStatus.cs +++ b/SnapX.Core/Upload/UploadInfoStatus.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/UploadManager.cs b/SnapX.Core/Upload/UploadManager.cs index 97bf67cdd..51383d518 100644 --- a/SnapX.Core/Upload/UploadManager.cs +++ b/SnapX.Core/Upload/UploadManager.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/UploadResult.cs b/SnapX.Core/Upload/UploadResult.cs index 396d1338a..521649e68 100644 --- a/SnapX.Core/Upload/UploadResult.cs +++ b/SnapX.Core/Upload/UploadResult.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/UploaderFactory.cs b/SnapX.Core/Upload/UploaderFactory.cs index bc8d5c36c..5c4e11887 100644 --- a/SnapX.Core/Upload/UploaderFactory.cs +++ b/SnapX.Core/Upload/UploaderFactory.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/UploaderFilter.cs b/SnapX.Core/Upload/UploaderFilter.cs index e20ecbc49..e3df00784 100644 --- a/SnapX.Core/Upload/UploaderFilter.cs +++ b/SnapX.Core/Upload/UploaderFilter.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/UploadersConfig.cs b/SnapX.Core/Upload/UploadersConfig.cs index f5b8ad24d..727fd330f 100644 --- a/SnapX.Core/Upload/UploadersConfig.cs +++ b/SnapX.Core/Upload/UploadersConfig.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/UploadersConfigValidator.cs b/SnapX.Core/Upload/UploadersConfigValidator.cs index c43dd5630..5a24b92d7 100644 --- a/SnapX.Core/Upload/UploadersConfigValidator.cs +++ b/SnapX.Core/Upload/UploadersConfigValidator.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Utils/AccountInfo.cs b/SnapX.Core/Upload/Utils/AccountInfo.cs index b53a303ef..1ba50a7fb 100644 --- a/SnapX.Core/Upload/Utils/AccountInfo.cs +++ b/SnapX.Core/Upload/Utils/AccountInfo.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Utils/Argument.cs b/SnapX.Core/Upload/Utils/Argument.cs index ff7f1b94a..6518e3cf8 100644 --- a/SnapX.Core/Upload/Utils/Argument.cs +++ b/SnapX.Core/Upload/Utils/Argument.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Utils/EscapeHelper.cs b/SnapX.Core/Upload/Utils/EscapeHelper.cs index a2492a08c..ac2c450c6 100644 --- a/SnapX.Core/Upload/Utils/EscapeHelper.cs +++ b/SnapX.Core/Upload/Utils/EscapeHelper.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Utils/ProgressManager.cs b/SnapX.Core/Upload/Utils/ProgressManager.cs index 2a7f9c0d6..d41f8479c 100644 --- a/SnapX.Core/Upload/Utils/ProgressManager.cs +++ b/SnapX.Core/Upload/Utils/ProgressManager.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Utils/RequestHelpers.cs b/SnapX.Core/Upload/Utils/RequestHelpers.cs index ed615dd63..e223c9ef4 100644 --- a/SnapX.Core/Upload/Utils/RequestHelpers.cs +++ b/SnapX.Core/Upload/Utils/RequestHelpers.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Utils/ResponseInfo.cs b/SnapX.Core/Upload/Utils/ResponseInfo.cs index aec5bebc0..8f228d267 100644 --- a/SnapX.Core/Upload/Utils/ResponseInfo.cs +++ b/SnapX.Core/Upload/Utils/ResponseInfo.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Utils/SSLBypassHelper.cs b/SnapX.Core/Upload/Utils/SSLBypassHelper.cs index 24ab1c0da..bec34a1b6 100644 --- a/SnapX.Core/Upload/Utils/SSLBypassHelper.cs +++ b/SnapX.Core/Upload/Utils/SSLBypassHelper.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Utils/TaskReferenceHelper.cs b/SnapX.Core/Upload/Utils/TaskReferenceHelper.cs index 67aaf160e..59eb271ea 100644 --- a/SnapX.Core/Upload/Utils/TaskReferenceHelper.cs +++ b/SnapX.Core/Upload/Utils/TaskReferenceHelper.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Utils/UploaderErrorInfo.cs b/SnapX.Core/Upload/Utils/UploaderErrorInfo.cs index 2e210041c..c8262d2b8 100644 --- a/SnapX.Core/Upload/Utils/UploaderErrorInfo.cs +++ b/SnapX.Core/Upload/Utils/UploaderErrorInfo.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Utils/UploaderErrorManager.cs b/SnapX.Core/Upload/Utils/UploaderErrorManager.cs index a125750bb..5c7a3b527 100644 --- a/SnapX.Core/Upload/Utils/UploaderErrorManager.cs +++ b/SnapX.Core/Upload/Utils/UploaderErrorManager.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Zip/ZipEntryInfo.cs b/SnapX.Core/Upload/Zip/ZipEntryInfo.cs index 432389bfa..27777f055 100644 --- a/SnapX.Core/Upload/Zip/ZipEntryInfo.cs +++ b/SnapX.Core/Upload/Zip/ZipEntryInfo.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Upload/Zip/ZipManager.cs b/SnapX.Core/Upload/Zip/ZipManager.cs index 45b337af5..6a307a24a 100644 --- a/SnapX.Core/Upload/Zip/ZipManager.cs +++ b/SnapX.Core/Upload/Zip/ZipManager.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/CaptureHelpers.cs b/SnapX.Core/Utils/CaptureHelpers.cs index 3039b83bf..f7cbef9f2 100644 --- a/SnapX.Core/Utils/CaptureHelpers.cs +++ b/SnapX.Core/Utils/CaptureHelpers.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Cryptographic/HashChecker.cs b/SnapX.Core/Utils/Cryptographic/HashChecker.cs index 2120252ce..2eeb56ca6 100644 --- a/SnapX.Core/Utils/Cryptographic/HashChecker.cs +++ b/SnapX.Core/Utils/Cryptographic/HashChecker.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Cryptographic/Translator.cs b/SnapX.Core/Utils/Cryptographic/Translator.cs index a5a56dab9..31251d0bc 100644 --- a/SnapX.Core/Utils/Cryptographic/Translator.cs +++ b/SnapX.Core/Utils/Cryptographic/Translator.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Cryptographic/TranslatorHelper.cs b/SnapX.Core/Utils/Cryptographic/TranslatorHelper.cs index ee7e3736a..633854a00 100644 --- a/SnapX.Core/Utils/Cryptographic/TranslatorHelper.cs +++ b/SnapX.Core/Utils/Cryptographic/TranslatorHelper.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/DNS/AdapterInfo.cs b/SnapX.Core/Utils/DNS/AdapterInfo.cs index 96b9eff31..27b9de824 100644 --- a/SnapX.Core/Utils/DNS/AdapterInfo.cs +++ b/SnapX.Core/Utils/DNS/AdapterInfo.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later using System.Net.NetworkInformation; diff --git a/SnapX.Core/Utils/DNS/DNSInfo.cs b/SnapX.Core/Utils/DNS/DNSInfo.cs index 02c12c0b0..fc00cb50b 100644 --- a/SnapX.Core/Utils/DNS/DNSInfo.cs +++ b/SnapX.Core/Utils/DNS/DNSInfo.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Extensions/EnumExtensions.cs b/SnapX.Core/Utils/Extensions/EnumExtensions.cs index a37b52e38..7b4a400ef 100644 --- a/SnapX.Core/Utils/Extensions/EnumExtensions.cs +++ b/SnapX.Core/Utils/Extensions/EnumExtensions.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Extensions/Extensions.cs b/SnapX.Core/Utils/Extensions/Extensions.cs index 68c5661ab..dcad94d00 100644 --- a/SnapX.Core/Utils/Extensions/Extensions.cs +++ b/SnapX.Core/Utils/Extensions/Extensions.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Extensions/NumberExtensions.cs b/SnapX.Core/Utils/Extensions/NumberExtensions.cs index 24e0af8d5..93926734b 100644 --- a/SnapX.Core/Utils/Extensions/NumberExtensions.cs +++ b/SnapX.Core/Utils/Extensions/NumberExtensions.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Extensions/ObjectExtensions.cs b/SnapX.Core/Utils/Extensions/ObjectExtensions.cs index c7e1aea7e..ac87012fc 100644 --- a/SnapX.Core/Utils/Extensions/ObjectExtensions.cs +++ b/SnapX.Core/Utils/Extensions/ObjectExtensions.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Extensions/StreamExtensions.cs b/SnapX.Core/Utils/Extensions/StreamExtensions.cs index deb8e431e..7dfec72c2 100644 --- a/SnapX.Core/Utils/Extensions/StreamExtensions.cs +++ b/SnapX.Core/Utils/Extensions/StreamExtensions.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Extensions/StringExtensions.cs b/SnapX.Core/Utils/Extensions/StringExtensions.cs index 4b48df2e7..46e598f0c 100644 --- a/SnapX.Core/Utils/Extensions/StringExtensions.cs +++ b/SnapX.Core/Utils/Extensions/StringExtensions.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Extensions/XMLExtensions.cs b/SnapX.Core/Utils/Extensions/XMLExtensions.cs index 7696ce3bc..05ed2a26b 100644 --- a/SnapX.Core/Utils/Extensions/XMLExtensions.cs +++ b/SnapX.Core/Utils/Extensions/XMLExtensions.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/FileDownloader.cs b/SnapX.Core/Utils/FileDownloader.cs index 45d6160dd..fcbcde35a 100644 --- a/SnapX.Core/Utils/FileDownloader.cs +++ b/SnapX.Core/Utils/FileDownloader.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/FileHelpers.cs b/SnapX.Core/Utils/FileHelpers.cs index 0724c839a..cdc14fefa 100644 --- a/SnapX.Core/Utils/FileHelpers.cs +++ b/SnapX.Core/Utils/FileHelpers.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Helpers.cs b/SnapX.Core/Utils/Helpers.cs index bb9f88140..26429e17d 100644 --- a/SnapX.Core/Utils/Helpers.cs +++ b/SnapX.Core/Utils/Helpers.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/JsonHelpers.cs b/SnapX.Core/Utils/JsonHelpers.cs index 874fb66bc..d96537f1d 100644 --- a/SnapX.Core/Utils/JsonHelpers.cs +++ b/SnapX.Core/Utils/JsonHelpers.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/MathHelpers.cs b/SnapX.Core/Utils/MathHelpers.cs index f16449545..568b7b834 100644 --- a/SnapX.Core/Utils/MathHelpers.cs +++ b/SnapX.Core/Utils/MathHelpers.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Miscellaneous/ExternalProgram.cs b/SnapX.Core/Utils/Miscellaneous/ExternalProgram.cs index a81b4da67..22335c7da 100644 --- a/SnapX.Core/Utils/Miscellaneous/ExternalProgram.cs +++ b/SnapX.Core/Utils/Miscellaneous/ExternalProgram.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Miscellaneous/FPSManager.cs b/SnapX.Core/Utils/Miscellaneous/FPSManager.cs index ca918300d..a0e403df0 100644 --- a/SnapX.Core/Utils/Miscellaneous/FPSManager.cs +++ b/SnapX.Core/Utils/Miscellaneous/FPSManager.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Miscellaneous/FastDateTime.cs b/SnapX.Core/Utils/Miscellaneous/FastDateTime.cs index 00af5b7a5..d306aaadb 100644 --- a/SnapX.Core/Utils/Miscellaneous/FastDateTime.cs +++ b/SnapX.Core/Utils/Miscellaneous/FastDateTime.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Miscellaneous/FixedSizedQueue.cs b/SnapX.Core/Utils/Miscellaneous/FixedSizedQueue.cs index da68b7343..6a9b4565a 100644 --- a/SnapX.Core/Utils/Miscellaneous/FixedSizedQueue.cs +++ b/SnapX.Core/Utils/Miscellaneous/FixedSizedQueue.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Miscellaneous/HelpersOptions.cs b/SnapX.Core/Utils/Miscellaneous/HelpersOptions.cs index 3aad0be08..378abe078 100644 --- a/SnapX.Core/Utils/Miscellaneous/HelpersOptions.cs +++ b/SnapX.Core/Utils/Miscellaneous/HelpersOptions.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Miscellaneous/HttpClientFactory.cs b/SnapX.Core/Utils/Miscellaneous/HttpClientFactory.cs index 188fece7e..3336fb985 100644 --- a/SnapX.Core/Utils/Miscellaneous/HttpClientFactory.cs +++ b/SnapX.Core/Utils/Miscellaneous/HttpClientFactory.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Miscellaneous/Links.cs b/SnapX.Core/Utils/Miscellaneous/Links.cs index 2dad568dd..ba39933bc 100644 --- a/SnapX.Core/Utils/Miscellaneous/Links.cs +++ b/SnapX.Core/Utils/Miscellaneous/Links.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Miscellaneous/MaxLengthStream.cs b/SnapX.Core/Utils/Miscellaneous/MaxLengthStream.cs index 57c6a832a..169a631f8 100644 --- a/SnapX.Core/Utils/Miscellaneous/MaxLengthStream.cs +++ b/SnapX.Core/Utils/Miscellaneous/MaxLengthStream.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Miscellaneous/MimeTypesPlus.cs b/SnapX.Core/Utils/Miscellaneous/MimeTypesPlus.cs index b3ec28e08..cb9933f5c 100644 --- a/SnapX.Core/Utils/Miscellaneous/MimeTypesPlus.cs +++ b/SnapX.Core/Utils/Miscellaneous/MimeTypesPlus.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Miscellaneous/PingHelper.cs b/SnapX.Core/Utils/Miscellaneous/PingHelper.cs index b1bd114c9..673a050c9 100644 --- a/SnapX.Core/Utils/Miscellaneous/PingHelper.cs +++ b/SnapX.Core/Utils/Miscellaneous/PingHelper.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Miscellaneous/PingResult.cs b/SnapX.Core/Utils/Miscellaneous/PingResult.cs index 73abb0dfe..ccac2bcdb 100644 --- a/SnapX.Core/Utils/Miscellaneous/PingResult.cs +++ b/SnapX.Core/Utils/Miscellaneous/PingResult.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Miscellaneous/ProxyInfo.cs b/SnapX.Core/Utils/Miscellaneous/ProxyInfo.cs index 0918093a1..906462a8a 100644 --- a/SnapX.Core/Utils/Miscellaneous/ProxyInfo.cs +++ b/SnapX.Core/Utils/Miscellaneous/ProxyInfo.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Miscellaneous/SevenZipManager.cs b/SnapX.Core/Utils/Miscellaneous/SevenZipManager.cs index d53caa370..9b2d91c0b 100644 --- a/SnapX.Core/Utils/Miscellaneous/SevenZipManager.cs +++ b/SnapX.Core/Utils/Miscellaneous/SevenZipManager.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Miscellaneous/StringLineReader.cs b/SnapX.Core/Utils/Miscellaneous/StringLineReader.cs index acf37397b..025d63774 100644 --- a/SnapX.Core/Utils/Miscellaneous/StringLineReader.cs +++ b/SnapX.Core/Utils/Miscellaneous/StringLineReader.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Parsers/CodeMenuEntry.cs b/SnapX.Core/Utils/Parsers/CodeMenuEntry.cs index a832d3184..3939da54f 100644 --- a/SnapX.Core/Utils/Parsers/CodeMenuEntry.cs +++ b/SnapX.Core/Utils/Parsers/CodeMenuEntry.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Random/RandomCrypto.cs b/SnapX.Core/Utils/Random/RandomCrypto.cs index 105b2e063..86dac8e4b 100644 --- a/SnapX.Core/Utils/Random/RandomCrypto.cs +++ b/SnapX.Core/Utils/Random/RandomCrypto.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/Random/RandomFast.cs b/SnapX.Core/Utils/Random/RandomFast.cs index 79b81c3cc..901df0c44 100644 --- a/SnapX.Core/Utils/Random/RandomFast.cs +++ b/SnapX.Core/Utils/Random/RandomFast.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/URLHelpers.cs b/SnapX.Core/Utils/URLHelpers.cs index 08121f4f0..d664b2411 100644 --- a/SnapX.Core/Utils/URLHelpers.cs +++ b/SnapX.Core/Utils/URLHelpers.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Utils/WebHelpers.cs b/SnapX.Core/Utils/WebHelpers.cs index 351d5e379..0a6ba1b9e 100644 --- a/SnapX.Core/Utils/WebHelpers.cs +++ b/SnapX.Core/Utils/WebHelpers.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Watch/WatchFolder.cs b/SnapX.Core/Watch/WatchFolder.cs index 9c1e541f6..d377c5b84 100644 --- a/SnapX.Core/Watch/WatchFolder.cs +++ b/SnapX.Core/Watch/WatchFolder.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Watch/WatchFolderManager.cs b/SnapX.Core/Watch/WatchFolderManager.cs index c613e247c..b45a2ed91 100644 --- a/SnapX.Core/Watch/WatchFolderManager.cs +++ b/SnapX.Core/Watch/WatchFolderManager.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/SnapX.Core/Watch/WatchFolderSettings.cs b/SnapX.Core/Watch/WatchFolderSettings.cs index ec1edf7c1..e26a06956 100644 --- a/SnapX.Core/Watch/WatchFolderSettings.cs +++ b/SnapX.Core/Watch/WatchFolderSettings.cs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-or-later From bc45a375b31d0717fe95580a574b9b3f00dc8bfe Mon Sep 17 00:00:00 2001 From: Brycen G Date: Thu, 17 Jul 2025 15:34:11 -0400 Subject: [PATCH 18/31] build: remove dependency on MimeTypes --- SnapX.Core/SnapX.Core.csproj | 10 +- .../Utils/Miscellaneous/MimeTypesPlus.cs | 1007 ----------------- 2 files changed, 1 insertion(+), 1016 deletions(-) delete mode 100644 SnapX.Core/Utils/Miscellaneous/MimeTypesPlus.cs diff --git a/SnapX.Core/SnapX.Core.csproj b/SnapX.Core/SnapX.Core.csproj index b6fcf49de..3fdb5bca6 100644 --- a/SnapX.Core/SnapX.Core.csproj +++ b/SnapX.Core/SnapX.Core.csproj @@ -55,11 +55,6 @@ - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - @@ -80,10 +75,7 @@ hiding them behind a compiler conditional makes debugging more difficult. --> - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - + diff --git a/SnapX.Core/Utils/Miscellaneous/MimeTypesPlus.cs b/SnapX.Core/Utils/Miscellaneous/MimeTypesPlus.cs deleted file mode 100644 index cb9933f5c..000000000 --- a/SnapX.Core/Utils/Miscellaneous/MimeTypesPlus.cs +++ /dev/null @@ -1,1007 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - - -namespace SnapX.Core.Utils.Miscellaneous; - -public static class MimeTypesPlus -{ - public static bool IsImageMimeType(string mimeType) - { - return !string.IsNullOrEmpty(mimeType) && - (mimeType.Equals(Mappings["png"], StringComparison.OrdinalIgnoreCase) || - mimeType.Equals(Mappings["apng"], StringComparison.OrdinalIgnoreCase) || - mimeType.Equals(Mappings["jpeg"], StringComparison.OrdinalIgnoreCase) || - mimeType.Equals(Mappings["gif"], StringComparison.OrdinalIgnoreCase) || - mimeType.Equals(Mappings["bmp"], StringComparison.OrdinalIgnoreCase) || - mimeType.Equals(Mappings["webp"], StringComparison.OrdinalIgnoreCase) || - mimeType.Equals(Mappings["tiff"], StringComparison.OrdinalIgnoreCase)); - } - - // http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types - private static Dictionary Mappings = new(StringComparer.OrdinalIgnoreCase) - { - { "123", "application/vnd.lotus-1-2-3" }, - { "3dml", "text/vnd.in3d.3dml" }, - { "3ds", "image/x-3ds" }, - { "3g2", "video/3gpp2" }, - { "3gp", "video/3gpp" }, - { "7z", "application/x-7z-compressed" }, - { "aab", "application/x-authorware-bin" }, - { "aac", "audio/x-aac" }, - { "aam", "application/x-authorware-map" }, - { "aas", "application/x-authorware-seg" }, - { "abw", "application/x-abiword" }, - { "ac", "application/pkix-attr-cert" }, - { "acc", "application/vnd.americandynamics.acc" }, - { "ace", "application/x-ace-compressed" }, - { "acu", "application/vnd.acucobol" }, - { "acutc", "application/vnd.acucorp" }, - { "adp", "audio/adpcm" }, - { "aep", "application/vnd.audiograph" }, - { "afm", "application/x-font-type1" }, - { "afp", "application/vnd.ibm.modcap" }, - { "ahead", "application/vnd.ahead.space" }, - { "ai", "application/postscript" }, - { "aif", "audio/x-aiff" }, - { "aifc", "audio/x-aiff" }, - { "aiff", "audio/x-aiff" }, - { "air", "application/vnd.adobe.air-application-installer-package+zip" }, - { "ait", "application/vnd.dvb.ait" }, - { "ami", "application/vnd.amiga.ami" }, - { "apk", "application/vnd.android.package-archive" }, - { "apng", "image/apng" }, - { "appcache", "text/cache-manifest" }, - { "application", "application/x-ms-application" }, - { "apr", "application/vnd.lotus-approach" }, - { "arc", "application/x-freearc" }, - { "asc", "application/pgp-signature" }, - { "asf", "video/x-ms-asf" }, - { "asm", "text/x-asm" }, - { "aso", "application/vnd.accpac.simply.aso" }, - { "asx", "video/x-ms-asf" }, - { "atc", "application/vnd.acucorp" }, - { "atom", "application/atom+xml" }, - { "atomcat", "application/atomcat+xml" }, - { "atomsvc", "application/atomsvc+xml" }, - { "atx", "application/vnd.antix.game-component" }, - { "au", "audio/basic" }, - { "avi", "video/x-msvideo" }, - { "aw", "application/applixware" }, - { "azf", "application/vnd.airzip.filesecure.azf" }, - { "azs", "application/vnd.airzip.filesecure.azs" }, - { "azw", "application/vnd.amazon.ebook" }, - { "bat", "application/x-msdownload" }, - { "bcpio", "application/x-bcpio" }, - { "bdf", "application/x-font-bdf" }, - { "bdm", "application/vnd.syncml.dm+wbxml" }, - { "bed", "application/vnd.realvnc.bed" }, - { "bh2", "application/vnd.fujitsu.oasysprs" }, - { "bin", "application/octet-stream" }, - { "blb", "application/x-blorb" }, - { "blorb", "application/x-blorb" }, - { "bmi", "application/vnd.bmi" }, - { "bmp", "image/bmp" }, - { "book", "application/vnd.framemaker" }, - { "box", "application/vnd.previewsystems.box" }, - { "boz", "application/x-bzip2" }, - { "bpk", "application/octet-stream" }, - { "btif", "image/prs.btif" }, - { "bz", "application/x-bzip" }, - { "bz2", "application/x-bzip2" }, - { "c", "text/x-c" }, - { "c11amc", "application/vnd.cluetrust.cartomobile-config" }, - { "c11amz", "application/vnd.cluetrust.cartomobile-config-pkg" }, - { "c4d", "application/vnd.clonk.c4group" }, - { "c4f", "application/vnd.clonk.c4group" }, - { "c4g", "application/vnd.clonk.c4group" }, - { "c4p", "application/vnd.clonk.c4group" }, - { "c4u", "application/vnd.clonk.c4group" }, - { "cab", "application/vnd.ms-cab-compressed" }, - { "caf", "audio/x-caf" }, - { "cap", "application/vnd.tcpdump.pcap" }, - { "car", "application/vnd.curl.car" }, - { "cat", "application/vnd.ms-pki.seccat" }, - { "cb7", "application/x-cbr" }, - { "cba", "application/x-cbr" }, - { "cbr", "application/x-cbr" }, - { "cbt", "application/x-cbr" }, - { "cbz", "application/x-cbr" }, - { "cc", "text/x-c" }, - { "cct", "application/x-director" }, - { "ccxml", "application/ccxml+xml" }, - { "cdbcmsg", "application/vnd.contact.cmsg" }, - { "cdf", "application/x-netcdf" }, - { "cdkey", "application/vnd.mediastation.cdkey" }, - { "cdmia", "application/cdmi-capability" }, - { "cdmic", "application/cdmi-container" }, - { "cdmid", "application/cdmi-domain" }, - { "cdmio", "application/cdmi-object" }, - { "cdmiq", "application/cdmi-queue" }, - { "cdx", "chemical/x-cdx" }, - { "cdxml", "application/vnd.chemdraw+xml" }, - { "cdy", "application/vnd.cinderella" }, - { "cer", "application/pkix-cert" }, - { "cfs", "application/x-cfs-compressed" }, - { "cgm", "image/cgm" }, - { "chat", "application/x-chat" }, - { "chm", "application/vnd.ms-htmlhelp" }, - { "chrt", "application/vnd.kde.kchart" }, - { "cif", "chemical/x-cif" }, - { "cii", "application/vnd.anser-web-certificate-issue-initiation" }, - { "cil", "application/vnd.ms-artgalry" }, - { "cla", "application/vnd.claymore" }, - { "class", "application/java-vm" }, - { "clkk", "application/vnd.crick.clicker.keyboard" }, - { "clkp", "application/vnd.crick.clicker.palette" }, - { "clkt", "application/vnd.crick.clicker.template" }, - { "clkw", "application/vnd.crick.clicker.wordbank" }, - { "clkx", "application/vnd.crick.clicker" }, - { "clp", "application/x-msclip" }, - { "cmc", "application/vnd.cosmocaller" }, - { "cmdf", "chemical/x-cmdf" }, - { "cml", "chemical/x-cml" }, - { "cmp", "application/vnd.yellowriver-custom-menu" }, - { "cmx", "image/x-cmx" }, - { "cod", "application/vnd.rim.cod" }, - { "com", "application/x-msdownload" }, - { "conf", "text/plain" }, - { "cpio", "application/x-cpio" }, - { "cpp", "text/x-c" }, - { "cpt", "application/mac-compactpro" }, - { "crd", "application/x-mscardfile" }, - { "crl", "application/pkix-crl" }, - { "crt", "application/x-x509-ca-cert" }, - { "cryptonote", "application/vnd.rig.cryptonote" }, - { "csh", "application/x-csh" }, - { "csml", "chemical/x-csml" }, - { "csp", "application/vnd.commonspace" }, - { "css", "text/css" }, - { "cst", "application/x-director" }, - { "csv", "text/csv" }, - { "cu", "application/cu-seeme" }, - { "curl", "text/vnd.curl" }, - { "cww", "application/prs.cww" }, - { "cxt", "application/x-director" }, - { "cxx", "text/x-c" }, - { "dae", "model/vnd.collada+xml" }, - { "daf", "application/vnd.mobius.daf" }, - { "dart", "application/vnd.dart" }, - { "dataless", "application/vnd.fdsn.seed" }, - { "davmount", "application/davmount+xml" }, - { "dbk", "application/docbook+xml" }, - { "dcr", "application/x-director" }, - { "dcurl", "text/vnd.curl.dcurl" }, - { "dd2", "application/vnd.oma.dd2+xml" }, - { "ddd", "application/vnd.fujixerox.ddd" }, - { "deb", "application/x-debian-package" }, - { "def", "text/plain" }, - { "deploy", "application/octet-stream" }, - { "der", "application/x-x509-ca-cert" }, - { "dfac", "application/vnd.dreamfactory" }, - { "dgc", "application/x-dgc-compressed" }, - { "dic", "text/x-c" }, - { "dir", "application/x-director" }, - { "dis", "application/vnd.mobius.dis" }, - { "dist", "application/octet-stream" }, - { "distz", "application/octet-stream" }, - { "djv", "image/vnd.djvu" }, - { "djvu", "image/vnd.djvu" }, - { "dll", "application/x-msdownload" }, - { "dmg", "application/x-apple-diskimage" }, - { "dmp", "application/vnd.tcpdump.pcap" }, - { "dms", "application/octet-stream" }, - { "dna", "application/vnd.dna" }, - { "doc", "application/msword" }, - { "docm", "application/vnd.ms-word.document.macroenabled.12" }, - { "docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document" }, - { "dot", "application/msword" }, - { "dotm", "application/vnd.ms-word.template.macroenabled.12" }, - { "dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template" }, - { "dp", "application/vnd.osgi.dp" }, - { "dpg", "application/vnd.dpgraph" }, - { "dra", "audio/vnd.dra" }, - { "dsc", "text/prs.lines.tag" }, - { "dssc", "application/dssc+der" }, - { "dtb", "application/x-dtbook+xml" }, - { "dtd", "application/xml-dtd" }, - { "dts", "audio/vnd.dts" }, - { "dtshd", "audio/vnd.dts.hd" }, - { "dump", "application/octet-stream" }, - { "dvb", "video/vnd.dvb.file" }, - { "dvi", "application/x-dvi" }, - { "dwf", "model/vnd.dwf" }, - { "dwg", "image/vnd.dwg" }, - { "dxf", "image/vnd.dxf" }, - { "dxp", "application/vnd.spotfire.dxp" }, - { "dxr", "application/x-director" }, - { "ecelp4800", "audio/vnd.nuera.ecelp4800" }, - { "ecelp7470", "audio/vnd.nuera.ecelp7470" }, - { "ecelp9600", "audio/vnd.nuera.ecelp9600" }, - { "ecma", "application/ecmascript" }, - { "edm", "application/vnd.novadigm.edm" }, - { "edx", "application/vnd.novadigm.edx" }, - { "efif", "application/vnd.picsel" }, - { "ei6", "application/vnd.pg.osasli" }, - { "elc", "application/octet-stream" }, - { "emf", "application/x-msmetafile" }, - { "eml", "message/rfc822" }, - { "emma", "application/emma+xml" }, - { "emz", "application/x-msmetafile" }, - { "eol", "audio/vnd.digital-winds" }, - { "eot", "application/vnd.ms-fontobject" }, - { "eps", "application/postscript" }, - { "epub", "application/epub+zip" }, - { "es3", "application/vnd.eszigno3+xml" }, - { "esa", "application/vnd.osgi.subsystem" }, - { "esf", "application/vnd.epson.esf" }, - { "et3", "application/vnd.eszigno3+xml" }, - { "etx", "text/x-setext" }, - { "eva", "application/x-eva" }, - { "evy", "application/x-envoy" }, - { "exe", "application/x-msdownload" }, - { "exi", "application/exi" }, - { "ext", "application/vnd.novadigm.ext" }, - { "ez", "application/andrew-inset" }, - { "ez2", "application/vnd.ezpix-album" }, - { "ez3", "application/vnd.ezpix-package" }, - { "f", "text/x-fortran" }, - { "f4v", "video/x-f4v" }, - { "f77", "text/x-fortran" }, - { "f90", "text/x-fortran" }, - { "fbs", "image/vnd.fastbidsheet" }, - { "fcdt", "application/vnd.adobe.formscentral.fcdt" }, - { "fcs", "application/vnd.isac.fcs" }, - { "fdf", "application/vnd.fdf" }, - { "fe_launch", "application/vnd.denovo.fcselayout-link" }, - { "fg5", "application/vnd.fujitsu.oasysgp" }, - { "fgd", "application/x-director" }, - { "fh", "image/x-freehand" }, - { "fh4", "image/x-freehand" }, - { "fh5", "image/x-freehand" }, - { "fh7", "image/x-freehand" }, - { "fhc", "image/x-freehand" }, - { "fig", "application/x-xfig" }, - { "flac", "audio/x-flac" }, - { "fli", "video/x-fli" }, - { "flo", "application/vnd.micrografx.flo" }, - { "flv", "video/x-flv" }, - { "flw", "application/vnd.kde.kivio" }, - { "flx", "text/vnd.fmi.flexstor" }, - { "fly", "text/vnd.fly" }, - { "fm", "application/vnd.framemaker" }, - { "fnc", "application/vnd.frogans.fnc" }, - { "for", "text/x-fortran" }, - { "fpx", "image/vnd.fpx" }, - { "frame", "application/vnd.framemaker" }, - { "fsc", "application/vnd.fsc.weblaunch" }, - { "fst", "image/vnd.fst" }, - { "ftc", "application/vnd.fluxtime.clip" }, - { "fti", "application/vnd.anser-web-funds-transfer-initiation" }, - { "fvt", "video/vnd.fvt" }, - { "fxp", "application/vnd.adobe.fxp" }, - { "fxpl", "application/vnd.adobe.fxp" }, - { "fzs", "application/vnd.fuzzysheet" }, - { "g2w", "application/vnd.geoplan" }, - { "g3", "image/g3fax" }, - { "g3w", "application/vnd.geospace" }, - { "gac", "application/vnd.groove-account" }, - { "gam", "application/x-tads" }, - { "gbr", "application/rpki-ghostbusters" }, - { "gca", "application/x-gca-compressed" }, - { "gdl", "model/vnd.gdl" }, - { "geo", "application/vnd.dynageo" }, - { "gex", "application/vnd.geometry-explorer" }, - { "ggb", "application/vnd.geogebra.file" }, - { "ggt", "application/vnd.geogebra.tool" }, - { "ghf", "application/vnd.groove-help" }, - { "gif", "image/gif" }, - { "gim", "application/vnd.groove-identity-message" }, - { "gml", "application/gml+xml" }, - { "gmx", "application/vnd.gmx" }, - { "gnumeric", "application/x-gnumeric" }, - { "gph", "application/vnd.flographit" }, - { "gpx", "application/gpx+xml" }, - { "gqf", "application/vnd.grafeq" }, - { "gqs", "application/vnd.grafeq" }, - { "gram", "application/srgs" }, - { "gramps", "application/x-gramps-xml" }, - { "gre", "application/vnd.geometry-explorer" }, - { "grv", "application/vnd.groove-injector" }, - { "grxml", "application/srgs+xml" }, - { "gsf", "application/x-font-ghostscript" }, - { "gtar", "application/x-gtar" }, - { "gtm", "application/vnd.groove-tool-message" }, - { "gtw", "model/vnd.gtw" }, - { "gv", "text/vnd.graphviz" }, - { "gxf", "application/gxf" }, - { "gxt", "application/vnd.geonext" }, - { "h", "text/x-c" }, - { "h261", "video/h261" }, - { "h263", "video/h263" }, - { "h264", "video/h264" }, - { "hal", "application/vnd.hal+xml" }, - { "hbci", "application/vnd.hbci" }, - { "hdf", "application/x-hdf" }, - { "hh", "text/x-c" }, - { "hlp", "application/winhlp" }, - { "hpgl", "application/vnd.hp-hpgl" }, - { "hpid", "application/vnd.hp-hpid" }, - { "hps", "application/vnd.hp-hps" }, - { "hqx", "application/mac-binhex40" }, - { "htke", "application/vnd.kenameaapp" }, - { "htm", "text/html" }, - { "html", "text/html" }, - { "hvd", "application/vnd.yamaha.hv-dic" }, - { "hvp", "application/vnd.yamaha.hv-voice" }, - { "hvs", "application/vnd.yamaha.hv-script" }, - { "i2g", "application/vnd.intergeo" }, - { "icc", "application/vnd.iccprofile" }, - { "ice", "x-conference/x-cooltalk" }, - { "icm", "application/vnd.iccprofile" }, - { "ico", "image/x-icon" }, - { "ics", "text/calendar" }, - { "ief", "image/ief" }, - { "ifb", "text/calendar" }, - { "ifm", "application/vnd.shana.informed.formdata" }, - { "iges", "model/iges" }, - { "igl", "application/vnd.igloader" }, - { "igm", "application/vnd.insors.igm" }, - { "igs", "model/iges" }, - { "igx", "application/vnd.micrografx.igx" }, - { "iif", "application/vnd.shana.informed.interchange" }, - { "imp", "application/vnd.accpac.simply.imp" }, - { "ims", "application/vnd.ms-ims" }, - { "in", "text/plain" }, - { "ink", "application/inkml+xml" }, - { "inkml", "application/inkml+xml" }, - { "install", "application/x-install-instructions" }, - { "iota", "application/vnd.astraea-software.iota" }, - { "ipfix", "application/ipfix" }, - { "ipk", "application/vnd.shana.informed.package" }, - { "irm", "application/vnd.ibm.rights-management" }, - { "irp", "application/vnd.irepository.package+xml" }, - { "iso", "application/x-iso9660-image" }, - { "itp", "application/vnd.shana.informed.formtemplate" }, - { "ivp", "application/vnd.immervision-ivp" }, - { "ivu", "application/vnd.immervision-ivu" }, - { "jad", "text/vnd.sun.j2me.app-descriptor" }, - { "jam", "application/vnd.jam" }, - { "jar", "application/java-archive" }, - { "java", "text/x-java-source" }, - { "jisp", "application/vnd.jisp" }, - { "jlt", "application/vnd.hp-jlyt" }, - { "jnlp", "application/x-java-jnlp-file" }, - { "joda", "application/vnd.joost.joda-archive" }, - { "jpe", "image/jpeg" }, - { "jpeg", "image/jpeg" }, - { "jpg", "image/jpeg" }, - { "jpgm", "video/jpm" }, - { "jpgv", "video/jpeg" }, - { "jpm", "video/jpm" }, - { "js", "application/javascript" }, - { "json", "application/json" }, - { "jsonml", "application/jsonml+json" }, - { "kar", "audio/midi" }, - { "karbon", "application/vnd.kde.karbon" }, - { "kfo", "application/vnd.kde.kformula" }, - { "kia", "application/vnd.kidspiration" }, - { "kml", "application/vnd.google-earth.kml+xml" }, - { "kmz", "application/vnd.google-earth.kmz" }, - { "kne", "application/vnd.kinar" }, - { "knp", "application/vnd.kinar" }, - { "kon", "application/vnd.kde.kontour" }, - { "kpr", "application/vnd.kde.kpresenter" }, - { "kpt", "application/vnd.kde.kpresenter" }, - { "kpxx", "application/vnd.ds-keypoint" }, - { "ksp", "application/vnd.kde.kspread" }, - { "ktr", "application/vnd.kahootz" }, - { "ktx", "image/ktx" }, - { "ktz", "application/vnd.kahootz" }, - { "kwd", "application/vnd.kde.kword" }, - { "kwt", "application/vnd.kde.kword" }, - { "lasxml", "application/vnd.las.las+xml" }, - { "latex", "application/x-latex" }, - { "lbd", "application/vnd.llamagraphics.life-balance.desktop" }, - { "lbe", "application/vnd.llamagraphics.life-balance.exchange+xml" }, - { "les", "application/vnd.hhe.lesson-player" }, - { "lha", "application/x-lzh-compressed" }, - { "link66", "application/vnd.route66.link66+xml" }, - { "list", "text/plain" }, - { "list3820", "application/vnd.ibm.modcap" }, - { "listafp", "application/vnd.ibm.modcap" }, - { "lnk", "application/x-ms-shortcut" }, - { "log", "text/plain" }, - { "lostxml", "application/lost+xml" }, - { "lrf", "application/octet-stream" }, - { "lrm", "application/vnd.ms-lrm" }, - { "ltf", "application/vnd.frogans.ltf" }, - { "lvp", "audio/vnd.lucent.voice" }, - { "lwp", "application/vnd.lotus-wordpro" }, - { "lzh", "application/x-lzh-compressed" }, - { "m13", "application/x-msmediaview" }, - { "m14", "application/x-msmediaview" }, - { "m1v", "video/mpeg" }, - { "m21", "application/mp21" }, - { "m2a", "audio/mpeg" }, - { "m2v", "video/mpeg" }, - { "m3a", "audio/mpeg" }, - { "m3u", "audio/x-mpegurl" }, - { "m3u8", "application/vnd.apple.mpegurl" }, - { "m4u", "video/vnd.mpegurl" }, - { "m4v", "video/x-m4v" }, - { "ma", "application/mathematica" }, - { "mads", "application/mads+xml" }, - { "mag", "application/vnd.ecowin.chart" }, - { "maker", "application/vnd.framemaker" }, - { "man", "text/troff" }, - { "mar", "application/octet-stream" }, - { "mathml", "application/mathml+xml" }, - { "mb", "application/mathematica" }, - { "mbk", "application/vnd.mobius.mbk" }, - { "mbox", "application/mbox" }, - { "mc1", "application/vnd.medcalcdata" }, - { "mcd", "application/vnd.mcd" }, - { "mcurl", "text/vnd.curl.mcurl" }, - { "mdb", "application/x-msaccess" }, - { "mdi", "image/vnd.ms-modi" }, - { "me", "text/troff" }, - { "mesh", "model/mesh" }, - { "meta4", "application/metalink4+xml" }, - { "metalink", "application/metalink+xml" }, - { "mets", "application/mets+xml" }, - { "mfm", "application/vnd.mfmp" }, - { "mft", "application/rpki-manifest" }, - { "mgp", "application/vnd.osgeo.mapguide.package" }, - { "mgz", "application/vnd.proteus.magazine" }, - { "mid", "audio/midi" }, - { "midi", "audio/midi" }, - { "mie", "application/x-mie" }, - { "mif", "application/vnd.mif" }, - { "mime", "message/rfc822" }, - { "mj2", "video/mj2" }, - { "mjp2", "video/mj2" }, - { "mk3d", "video/x-matroska" }, - { "mka", "audio/x-matroska" }, - { "mks", "video/x-matroska" }, - { "mkv", "video/x-matroska" }, - { "mlp", "application/vnd.dolby.mlp" }, - { "mmd", "application/vnd.chipnuts.karaoke-mmd" }, - { "mmf", "application/vnd.smaf" }, - { "mmr", "image/vnd.fujixerox.edmics-mmr" }, - { "mng", "video/x-mng" }, - { "mny", "application/x-msmoney" }, - { "mobi", "application/x-mobipocket-ebook" }, - { "mods", "application/mods+xml" }, - { "mov", "video/quicktime" }, - { "movie", "video/x-sgi-movie" }, - { "mp2", "audio/mpeg" }, - { "mp21", "application/mp21" }, - { "mp2a", "audio/mpeg" }, - { "mp3", "audio/mpeg" }, - { "mp4", "video/mp4" }, - { "mp4a", "audio/mp4" }, - { "mp4s", "application/mp4" }, - { "mp4v", "video/mp4" }, - { "mpc", "application/vnd.mophun.certificate" }, - { "mpe", "video/mpeg" }, - { "mpeg", "video/mpeg" }, - { "mpg", "video/mpeg" }, - { "mpg4", "video/mp4" }, - { "mpga", "audio/mpeg" }, - { "mpkg", "application/vnd.apple.installer+xml" }, - { "mpm", "application/vnd.blueice.multipass" }, - { "mpn", "application/vnd.mophun.application" }, - { "mpp", "application/vnd.ms-project" }, - { "mpt", "application/vnd.ms-project" }, - { "mpy", "application/vnd.ibm.minipay" }, - { "mqy", "application/vnd.mobius.mqy" }, - { "mrc", "application/marc" }, - { "mrcx", "application/marcxml+xml" }, - { "ms", "text/troff" }, - { "mscml", "application/mediaservercontrol+xml" }, - { "mseed", "application/vnd.fdsn.mseed" }, - { "mseq", "application/vnd.mseq" }, - { "msf", "application/vnd.epson.msf" }, - { "msh", "model/mesh" }, - { "msi", "application/x-msdownload" }, - { "msl", "application/vnd.mobius.msl" }, - { "msty", "application/vnd.muvee.style" }, - { "mts", "model/vnd.mts" }, - { "mus", "application/vnd.musician" }, - { "musicxml", "application/vnd.recordare.musicxml+xml" }, - { "mvb", "application/x-msmediaview" }, - { "mwf", "application/vnd.mfer" }, - { "mxf", "application/mxf" }, - { "mxl", "application/vnd.recordare.musicxml" }, - { "mxml", "application/xv+xml" }, - { "mxs", "application/vnd.triscape.mxs" }, - { "mxu", "video/vnd.mpegurl" }, - { "n3", "text/n3" }, - { "nb", "application/mathematica" }, - { "nbp", "application/vnd.wolfram.player" }, - { "nc", "application/x-netcdf" }, - { "ncx", "application/x-dtbncx+xml" }, - { "nfo", "text/x-nfo" }, - { "n-gage", "application/vnd.nokia.n-gage.symbian.install" }, - { "ngdat", "application/vnd.nokia.n-gage.data" }, - { "nitf", "application/vnd.nitf" }, - { "nlu", "application/vnd.neurolanguage.nlu" }, - { "nml", "application/vnd.enliven" }, - { "nnd", "application/vnd.noblenet-directory" }, - { "nns", "application/vnd.noblenet-sealer" }, - { "nnw", "application/vnd.noblenet-web" }, - { "npx", "image/vnd.net-fpx" }, - { "nsc", "application/x-conference" }, - { "nsf", "application/vnd.lotus-notes" }, - { "ntf", "application/vnd.nitf" }, - { "nzb", "application/x-nzb" }, - { "oa2", "application/vnd.fujitsu.oasys2" }, - { "oa3", "application/vnd.fujitsu.oasys3" }, - { "oas", "application/vnd.fujitsu.oasys" }, - { "obd", "application/x-msbinder" }, - { "obj", "application/x-tgif" }, - { "oda", "application/oda" }, - { "odb", "application/vnd.oasis.opendocument.database" }, - { "odc", "application/vnd.oasis.opendocument.chart" }, - { "odf", "application/vnd.oasis.opendocument.formula" }, - { "odft", "application/vnd.oasis.opendocument.formula-template" }, - { "odg", "application/vnd.oasis.opendocument.graphics" }, - { "odi", "application/vnd.oasis.opendocument.image" }, - { "odm", "application/vnd.oasis.opendocument.text-master" }, - { "odp", "application/vnd.oasis.opendocument.presentation" }, - { "ods", "application/vnd.oasis.opendocument.spreadsheet" }, - { "odt", "application/vnd.oasis.opendocument.text" }, - { "oga", "audio/ogg" }, - { "ogg", "audio/ogg" }, - { "ogv", "video/ogg" }, - { "ogx", "application/ogg" }, - { "omdoc", "application/omdoc+xml" }, - { "onepkg", "application/onenote" }, - { "onetmp", "application/onenote" }, - { "onetoc", "application/onenote" }, - { "onetoc2", "application/onenote" }, - { "opf", "application/oebps-package+xml" }, - { "opml", "text/x-opml" }, - { "oprc", "application/vnd.palm" }, - { "org", "application/vnd.lotus-organizer" }, - { "osf", "application/vnd.yamaha.openscoreformat" }, - { "osfpvg", "application/vnd.yamaha.openscoreformat.osfpvg+xml" }, - { "otc", "application/vnd.oasis.opendocument.chart-template" }, - { "otf", "application/x-font-otf" }, - { "otg", "application/vnd.oasis.opendocument.graphics-template" }, - { "oth", "application/vnd.oasis.opendocument.text-web" }, - { "oti", "application/vnd.oasis.opendocument.image-template" }, - { "otp", "application/vnd.oasis.opendocument.presentation-template" }, - { "ots", "application/vnd.oasis.opendocument.spreadsheet-template" }, - { "ott", "application/vnd.oasis.opendocument.text-template" }, - { "oxps", "application/oxps" }, - { "oxt", "application/vnd.openofficeorg.extension" }, - { "p", "text/x-pascal" }, - { "p10", "application/pkcs10" }, - { "p12", "application/x-pkcs12" }, - { "p7b", "application/x-pkcs7-certificates" }, - { "p7c", "application/pkcs7-mime" }, - { "p7m", "application/pkcs7-mime" }, - { "p7r", "application/x-pkcs7-certreqresp" }, - { "p7s", "application/pkcs7-signature" }, - { "p8", "application/pkcs8" }, - { "pas", "text/x-pascal" }, - { "paw", "application/vnd.pawaafile" }, - { "pbd", "application/vnd.powerbuilder6" }, - { "pbm", "image/x-portable-bitmap" }, - { "pcap", "application/vnd.tcpdump.pcap" }, - { "pcf", "application/x-font-pcf" }, - { "pcl", "application/vnd.hp-pcl" }, - { "pclxl", "application/vnd.hp-pclxl" }, - { "pct", "image/x-pict" }, - { "pcurl", "application/vnd.curl.pcurl" }, - { "pcx", "image/x-pcx" }, - { "pdb", "application/vnd.palm" }, - { "pdf", "application/pdf" }, - { "pfa", "application/x-font-type1" }, - { "pfb", "application/x-font-type1" }, - { "pfm", "application/x-font-type1" }, - { "pfr", "application/font-tdpfr" }, - { "pfx", "application/x-pkcs12" }, - { "pgm", "image/x-portable-graymap" }, - { "pgn", "application/x-chess-pgn" }, - { "pgp", "application/pgp-encrypted" }, - { "pic", "image/x-pict" }, - { "pkg", "application/octet-stream" }, - { "pki", "application/pkixcmp" }, - { "pkipath", "application/pkix-pkipath" }, - { "plb", "application/vnd.3gpp.pic-bw-large" }, - { "plc", "application/vnd.mobius.plc" }, - { "plf", "application/vnd.pocketlearn" }, - { "pls", "application/pls+xml" }, - { "pml", "application/vnd.ctc-posml" }, - { "png", "image/png" }, - { "pnm", "image/x-portable-anymap" }, - { "portpkg", "application/vnd.macports.portpkg" }, - { "pot", "application/vnd.ms-powerpoint" }, - { "potm", "application/vnd.ms-powerpoint.template.macroenabled.12" }, - { "potx", "application/vnd.openxmlformats-officedocument.presentationml.template" }, - { "ppam", "application/vnd.ms-powerpoint.addin.macroenabled.12" }, - { "ppd", "application/vnd.cups-ppd" }, - { "ppm", "image/x-portable-pixmap" }, - { "pps", "application/vnd.ms-powerpoint" }, - { "ppsm", "application/vnd.ms-powerpoint.slideshow.macroenabled.12" }, - { "ppsx", "application/vnd.openxmlformats-officedocument.presentationml.slideshow" }, - { "ppt", "application/vnd.ms-powerpoint" }, - { "pptm", "application/vnd.ms-powerpoint.presentation.macroenabled.12" }, - { "pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation" }, - { "pqa", "application/vnd.palm" }, - { "prc", "application/x-mobipocket-ebook" }, - { "pre", "application/vnd.lotus-freelance" }, - { "prf", "application/pics-rules" }, - { "ps", "application/postscript" }, - { "psb", "application/vnd.3gpp.pic-bw-small" }, - { "psd", "image/vnd.adobe.photoshop" }, - { "psf", "application/x-font-linux-psf" }, - { "pskcxml", "application/pskc+xml" }, - { "ptid", "application/vnd.pvi.ptid1" }, - { "pub", "application/x-mspublisher" }, - { "pvb", "application/vnd.3gpp.pic-bw-var" }, - { "pwn", "application/vnd.3m.post-it-notes" }, - { "pya", "audio/vnd.ms-playready.media.pya" }, - { "pyv", "video/vnd.ms-playready.media.pyv" }, - { "qam", "application/vnd.epson.quickanime" }, - { "qbo", "application/vnd.intu.qbo" }, - { "qfx", "application/vnd.intu.qfx" }, - { "qps", "application/vnd.publishare-delta-tree" }, - { "qt", "video/quicktime" }, - { "qwd", "application/vnd.quark.quarkxpress" }, - { "qwt", "application/vnd.quark.quarkxpress" }, - { "qxb", "application/vnd.quark.quarkxpress" }, - { "qxd", "application/vnd.quark.quarkxpress" }, - { "qxl", "application/vnd.quark.quarkxpress" }, - { "qxt", "application/vnd.quark.quarkxpress" }, - { "ra", "audio/x-pn-realaudio" }, - { "ram", "audio/x-pn-realaudio" }, - { "rar", "application/x-rar-compressed" }, - { "ras", "image/x-cmu-raster" }, - { "rcprofile", "application/vnd.ipunplugged.rcprofile" }, - { "rdf", "application/rdf+xml" }, - { "rdz", "application/vnd.data-vision.rdz" }, - { "rep", "application/vnd.businessobjects" }, - { "res", "application/x-dtbresource+xml" }, - { "rgb", "image/x-rgb" }, - { "rif", "application/reginfo+xml" }, - { "rip", "audio/vnd.rip" }, - { "ris", "application/x-research-info-systems" }, - { "rl", "application/resource-lists+xml" }, - { "rlc", "image/vnd.fujixerox.edmics-rlc" }, - { "rld", "application/resource-lists-diff+xml" }, - { "rm", "application/vnd.rn-realmedia" }, - { "rmi", "audio/midi" }, - { "rmp", "audio/x-pn-realaudio-plugin" }, - { "rms", "application/vnd.jcp.javame.midlet-rms" }, - { "rmvb", "application/vnd.rn-realmedia-vbr" }, - { "rnc", "application/relax-ng-compact-syntax" }, - { "roa", "application/rpki-roa" }, - { "roff", "text/troff" }, - { "rp9", "application/vnd.cloanto.rp9" }, - { "rpss", "application/vnd.nokia.radio-presets" }, - { "rpst", "application/vnd.nokia.radio-preset" }, - { "rq", "application/sparql-query" }, - { "rs", "application/rls-services+xml" }, - { "rsd", "application/rsd+xml" }, - { "rss", "application/rss+xml" }, - { "rtf", "application/rtf" }, - { "rtx", "text/richtext" }, - { "s", "text/x-asm" }, - { "s3m", "audio/s3m" }, - { "saf", "application/vnd.yamaha.smaf-audio" }, - { "sbml", "application/sbml+xml" }, - { "sc", "application/vnd.ibm.secure-container" }, - { "scd", "application/x-msschedule" }, - { "scm", "application/vnd.lotus-screencam" }, - { "scq", "application/scvp-cv-request" }, - { "scs", "application/scvp-cv-response" }, - { "scurl", "text/vnd.curl.scurl" }, - { "sda", "application/vnd.stardivision.draw" }, - { "sdc", "application/vnd.stardivision.calc" }, - { "sdd", "application/vnd.stardivision.impress" }, - { "sdkd", "application/vnd.solent.sdkm+xml" }, - { "sdkm", "application/vnd.solent.sdkm+xml" }, - { "sdp", "application/sdp" }, - { "sdw", "application/vnd.stardivision.writer" }, - { "see", "application/vnd.seemail" }, - { "seed", "application/vnd.fdsn.seed" }, - { "sema", "application/vnd.sema" }, - { "semd", "application/vnd.semd" }, - { "semf", "application/vnd.semf" }, - { "ser", "application/java-serialized-object" }, - { "setpay", "application/set-payment-initiation" }, - { "setreg", "application/set-registration-initiation" }, - { "sfd-hdstx", "application/vnd.hydrostatix.sof-data" }, - { "sfs", "application/vnd.spotfire.sfs" }, - { "sfv", "text/x-sfv" }, - { "sgi", "image/sgi" }, - { "sgl", "application/vnd.stardivision.writer-global" }, - { "sgm", "text/sgml" }, - { "sgml", "text/sgml" }, - { "sh", "application/x-sh" }, - { "shar", "application/x-shar" }, - { "shf", "application/shf+xml" }, - { "sid", "image/x-mrsid-image" }, - { "sig", "application/pgp-signature" }, - { "sil", "audio/silk" }, - { "silo", "model/mesh" }, - { "sis", "application/vnd.symbian.install" }, - { "sisx", "application/vnd.symbian.install" }, - { "sit", "application/x-stuffit" }, - { "sitx", "application/x-stuffitx" }, - { "skd", "application/vnd.koan" }, - { "skm", "application/vnd.koan" }, - { "skp", "application/vnd.koan" }, - { "skt", "application/vnd.koan" }, - { "sldm", "application/vnd.ms-powerpoint.slide.macroenabled.12" }, - { "sldx", "application/vnd.openxmlformats-officedocument.presentationml.slide" }, - { "slt", "application/vnd.epson.salt" }, - { "sm", "application/vnd.stepmania.stepchart" }, - { "smf", "application/vnd.stardivision.math" }, - { "smi", "application/smil+xml" }, - { "smil", "application/smil+xml" }, - { "smv", "video/x-smv" }, - { "smzip", "application/vnd.stepmania.package" }, - { "snd", "audio/basic" }, - { "snf", "application/x-font-snf" }, - { "so", "application/octet-stream" }, - { "spc", "application/x-pkcs7-certificates" }, - { "spf", "application/vnd.yamaha.smaf-phrase" }, - { "spl", "application/x-futuresplash" }, - { "spot", "text/vnd.in3d.spot" }, - { "spp", "application/scvp-vp-response" }, - { "spq", "application/scvp-vp-request" }, - { "spx", "audio/ogg" }, - { "sql", "application/x-sql" }, - { "src", "application/x-wais-source" }, - { "srt", "application/x-subrip" }, - { "sru", "application/sru+xml" }, - { "srx", "application/sparql-results+xml" }, - { "ssdl", "application/ssdl+xml" }, - { "sse", "application/vnd.kodak-descriptor" }, - { "ssf", "application/vnd.epson.ssf" }, - { "ssml", "application/ssml+xml" }, - { "st", "application/vnd.sailingtracker.track" }, - { "stc", "application/vnd.sun.xml.calc.template" }, - { "std", "application/vnd.sun.xml.draw.template" }, - { "stf", "application/vnd.wt.stf" }, - { "sti", "application/vnd.sun.xml.impress.template" }, - { "stk", "application/hyperstudio" }, - { "stl", "application/vnd.ms-pki.stl" }, - { "str", "application/vnd.pg.format" }, - { "stw", "application/vnd.sun.xml.writer.template" }, - { "sub", "image/vnd.dvb.subtitle" }, - { "sus", "application/vnd.sus-calendar" }, - { "susp", "application/vnd.sus-calendar" }, - { "sv4cpio", "application/x-sv4cpio" }, - { "sv4crc", "application/x-sv4crc" }, - { "svc", "application/vnd.dvb.service" }, - { "svd", "application/vnd.svd" }, - { "svg", "image/svg+xml" }, - { "svgz", "image/svg+xml" }, - { "swa", "application/x-director" }, - { "swf", "application/x-shockwave-flash" }, - { "swi", "application/vnd.aristanetworks.swi" }, - { "sxc", "application/vnd.sun.xml.calc" }, - { "sxd", "application/vnd.sun.xml.draw" }, - { "sxg", "application/vnd.sun.xml.writer.global" }, - { "sxi", "application/vnd.sun.xml.impress" }, - { "sxm", "application/vnd.sun.xml.math" }, - { "sxw", "application/vnd.sun.xml.writer" }, - { "t", "text/troff" }, - { "t3", "application/x-t3vm-image" }, - { "taglet", "application/vnd.mynfc" }, - { "tao", "application/vnd.tao.intent-module-archive" }, - { "tar", "application/x-tar" }, - { "tcap", "application/vnd.3gpp2.tcap" }, - { "tcl", "application/x-tcl" }, - { "teacher", "application/vnd.smart.teacher" }, - { "tei", "application/tei+xml" }, - { "teicorpus", "application/tei+xml" }, - { "tex", "application/x-tex" }, - { "texi", "application/x-texinfo" }, - { "texinfo", "application/x-texinfo" }, - { "text", "text/plain" }, - { "tfi", "application/thraud+xml" }, - { "tfm", "application/x-tex-tfm" }, - { "tga", "image/x-tga" }, - { "thmx", "application/vnd.ms-officetheme" }, - { "tif", "image/tiff" }, - { "tiff", "image/tiff" }, - { "tmo", "application/vnd.tmobile-livetv" }, - { "torrent", "application/x-bittorrent" }, - { "tpl", "application/vnd.groove-tool-template" }, - { "tpt", "application/vnd.trid.tpt" }, - { "tr", "text/troff" }, - { "tra", "application/vnd.trueapp" }, - { "trm", "application/x-msterminal" }, - { "tsd", "application/timestamped-data" }, - { "tsv", "text/tab-separated-values" }, - { "ttc", "application/x-font-ttf" }, - { "ttf", "application/x-font-ttf" }, - { "ttl", "text/turtle" }, - { "twd", "application/vnd.simtech-mindmapper" }, - { "twds", "application/vnd.simtech-mindmapper" }, - { "txd", "application/vnd.genomatix.tuxedo" }, - { "txf", "application/vnd.mobius.txf" }, - { "txt", "text/plain" }, - { "u32", "application/x-authorware-bin" }, - { "udeb", "application/x-debian-package" }, - { "ufd", "application/vnd.ufdl" }, - { "ufdl", "application/vnd.ufdl" }, - { "ulx", "application/x-glulx" }, - { "umj", "application/vnd.umajin" }, - { "unityweb", "application/vnd.unity" }, - { "uoml", "application/vnd.uoml+xml" }, - { "uri", "text/uri-list" }, - { "uris", "text/uri-list" }, - { "urls", "text/uri-list" }, - { "ustar", "application/x-ustar" }, - { "utz", "application/vnd.uiq.theme" }, - { "uu", "text/x-uuencode" }, - { "uva", "audio/vnd.dece.audio" }, - { "uvd", "application/vnd.dece.data" }, - { "uvf", "application/vnd.dece.data" }, - { "uvg", "image/vnd.dece.graphic" }, - { "uvh", "video/vnd.dece.hd" }, - { "uvi", "image/vnd.dece.graphic" }, - { "uvm", "video/vnd.dece.mobile" }, - { "uvp", "video/vnd.dece.pd" }, - { "uvs", "video/vnd.dece.sd" }, - { "uvt", "application/vnd.dece.ttml+xml" }, - { "uvu", "video/vnd.uvvu.mp4" }, - { "uvv", "video/vnd.dece.video" }, - { "uvva", "audio/vnd.dece.audio" }, - { "uvvd", "application/vnd.dece.data" }, - { "uvvf", "application/vnd.dece.data" }, - { "uvvg", "image/vnd.dece.graphic" }, - { "uvvh", "video/vnd.dece.hd" }, - { "uvvi", "image/vnd.dece.graphic" }, - { "uvvm", "video/vnd.dece.mobile" }, - { "uvvp", "video/vnd.dece.pd" }, - { "uvvs", "video/vnd.dece.sd" }, - { "uvvt", "application/vnd.dece.ttml+xml" }, - { "uvvu", "video/vnd.uvvu.mp4" }, - { "uvvv", "video/vnd.dece.video" }, - { "uvvx", "application/vnd.dece.unspecified" }, - { "uvvz", "application/vnd.dece.zip" }, - { "uvx", "application/vnd.dece.unspecified" }, - { "uvz", "application/vnd.dece.zip" }, - { "vcard", "text/vcard" }, - { "vcd", "application/x-cdlink" }, - { "vcf", "text/x-vcard" }, - { "vcg", "application/vnd.groove-vcard" }, - { "vcs", "text/x-vcalendar" }, - { "vcx", "application/vnd.vcx" }, - { "vis", "application/vnd.visionary" }, - { "viv", "video/vnd.vivo" }, - { "vob", "video/x-ms-vob" }, - { "vor", "application/vnd.stardivision.writer" }, - { "vox", "application/x-authorware-bin" }, - { "vrml", "model/vrml" }, - { "vsd", "application/vnd.visio" }, - { "vsf", "application/vnd.vsf" }, - { "vss", "application/vnd.visio" }, - { "vst", "application/vnd.visio" }, - { "vsw", "application/vnd.visio" }, - { "vtu", "model/vnd.vtu" }, - { "vxml", "application/voicexml+xml" }, - { "w3d", "application/x-director" }, - { "wad", "application/x-doom" }, - { "wav", "audio/x-wav" }, - { "wax", "audio/x-ms-wax" }, - { "wbmp", "image/vnd.wap.wbmp" }, - { "wbs", "application/vnd.criticaltools.wbs+xml" }, - { "wbxml", "application/vnd.wap.wbxml" }, - { "wcm", "application/vnd.ms-works" }, - { "wdb", "application/vnd.ms-works" }, - { "wdp", "image/vnd.ms-photo" }, - { "weba", "audio/webm" }, - { "webm", "video/webm" }, - { "webp", "image/webp" }, - { "wg", "application/vnd.pmi.widget" }, - { "wgt", "application/widget" }, - { "wks", "application/vnd.ms-works" }, - { "wm", "video/x-ms-wm" }, - { "wma", "audio/x-ms-wma" }, - { "wmd", "application/x-ms-wmd" }, - { "wmf", "application/x-msmetafile" }, - { "wml", "text/vnd.wap.wml" }, - { "wmlc", "application/vnd.wap.wmlc" }, - { "wmls", "text/vnd.wap.wmlscript" }, - { "wmlsc", "application/vnd.wap.wmlscriptc" }, - { "wmv", "video/x-ms-wmv" }, - { "wmx", "video/x-ms-wmx" }, - { "wmz", "application/x-ms-wmz" }, - { "woff", "application/font-woff" }, - { "wpd", "application/vnd.wordperfect" }, - { "wpl", "application/vnd.ms-wpl" }, - { "wps", "application/vnd.ms-works" }, - { "wqd", "application/vnd.wqd" }, - { "wri", "application/x-mswrite" }, - { "wrl", "model/vrml" }, - { "wsdl", "application/wsdl+xml" }, - { "wspolicy", "application/wspolicy+xml" }, - { "wtb", "application/vnd.webturbo" }, - { "wvx", "video/x-ms-wvx" }, - { "x32", "application/x-authorware-bin" }, - { "x3d", "model/x3d+xml" }, - { "x3db", "model/x3d+binary" }, - { "x3dbz", "model/x3d+binary" }, - { "x3dv", "model/x3d+vrml" }, - { "x3dvz", "model/x3d+vrml" }, - { "x3dz", "model/x3d+xml" }, - { "xaml", "application/xaml+xml" }, - { "xap", "application/x-silverlight-app" }, - { "xar", "application/vnd.xara" }, - { "xbap", "application/x-ms-xbap" }, - { "xbd", "application/vnd.fujixerox.docuworks.binder" }, - { "xbm", "image/x-xbitmap" }, - { "xdf", "application/xcap-diff+xml" }, - { "xdm", "application/vnd.syncml.dm+xml" }, - { "xdp", "application/vnd.adobe.xdp+xml" }, - { "xdssc", "application/dssc+xml" }, - { "xdw", "application/vnd.fujixerox.docuworks" }, - { "xenc", "application/xenc+xml" }, - { "xer", "application/patch-ops-error+xml" }, - { "xfdf", "application/vnd.adobe.xfdf" }, - { "xfdl", "application/vnd.xfdl" }, - { "xht", "application/xhtml+xml" }, - { "xhtml", "application/xhtml+xml" }, - { "xhvml", "application/xv+xml" }, - { "xif", "image/vnd.xiff" }, - { "xla", "application/vnd.ms-excel" }, - { "xlam", "application/vnd.ms-excel.addin.macroenabled.12" }, - { "xlc", "application/vnd.ms-excel" }, - { "xlf", "application/x-xliff+xml" }, - { "xlm", "application/vnd.ms-excel" }, - { "xls", "application/vnd.ms-excel" }, - { "xlsb", "application/vnd.ms-excel.sheet.binary.macroenabled.12" }, - { "xlsm", "application/vnd.ms-excel.sheet.macroenabled.12" }, - { "xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" }, - { "xlt", "application/vnd.ms-excel" }, - { "xltm", "application/vnd.ms-excel.template.macroenabled.12" }, - { "xltx", "application/vnd.openxmlformats-officedocument.spreadsheetml.template" }, - { "xlw", "application/vnd.ms-excel" }, - { "xm", "audio/xm" }, - { "xml", "application/xml" }, - { "xo", "application/vnd.olpc-sugar" }, - { "xop", "application/xop+xml" }, - { "xpi", "application/x-xpinstall" }, - { "xpl", "application/xproc+xml" }, - { "xpm", "image/x-xpixmap" }, - { "xpr", "application/vnd.is-xpr" }, - { "xps", "application/vnd.ms-xpsdocument" }, - { "xpw", "application/vnd.intercon.formnet" }, - { "xpx", "application/vnd.intercon.formnet" }, - { "xsl", "application/xml" }, - { "xslt", "application/xslt+xml" }, - { "xsm", "application/vnd.syncml+xml" }, - { "xspf", "application/xspf+xml" }, - { "xul", "application/vnd.mozilla.xul+xml" }, - { "xvm", "application/xv+xml" }, - { "xvml", "application/xv+xml" }, - { "xwd", "image/x-xwindowdump" }, - { "xyz", "chemical/x-xyz" }, - { "xz", "application/x-xz" }, - { "yang", "application/yang" }, - { "yin", "application/yin+xml" }, - { "z1", "application/x-zmachine" }, - { "z2", "application/x-zmachine" }, - { "z3", "application/x-zmachine" }, - { "z4", "application/x-zmachine" }, - { "z5", "application/x-zmachine" }, - { "z6", "application/x-zmachine" }, - { "z7", "application/x-zmachine" }, - { "z8", "application/x-zmachine" }, - { "zaz", "application/vnd.zzazz.deck+xml" }, - { "zip", "application/zip" }, - { "zir", "application/vnd.zul" }, - { "zirz", "application/vnd.zul" }, - { "zmm", "application/vnd.handheld-entertainment+xml" } - }; -} - From a46ccc06d46460ebf99ad53bff863e0ece11e8e6 Mon Sep 17 00:00:00 2001 From: Brycen G Date: Thu, 17 Jul 2025 15:34:34 -0400 Subject: [PATCH 19/31] style: remove dead classes --- .../Utils/Miscellaneous/FastDateTime.cs | 37 ----------- .../Utils/Miscellaneous/StringLineReader.cs | 66 ------------------- 2 files changed, 103 deletions(-) delete mode 100644 SnapX.Core/Utils/Miscellaneous/FastDateTime.cs delete mode 100644 SnapX.Core/Utils/Miscellaneous/StringLineReader.cs diff --git a/SnapX.Core/Utils/Miscellaneous/FastDateTime.cs b/SnapX.Core/Utils/Miscellaneous/FastDateTime.cs deleted file mode 100644 index d306aaadb..000000000 --- a/SnapX.Core/Utils/Miscellaneous/FastDateTime.cs +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - - - -namespace SnapX.Core.Utils.Miscellaneous; - -public static class FastDateTime -{ - public static TimeSpan LocalUtcOffset { get; private set; } - - public static DateTime Now - { - get - { - return ToLocalTime(DateTime.UtcNow); - } - } - - public static long NowUnix - { - get - { - return (DateTime.UtcNow.Ticks - 621355968000000000) / 10000000; - } - } - - static FastDateTime() - { - LocalUtcOffset = TimeZoneInfo.Local.GetUtcOffset(DateTime.Now); - } - - public static DateTime ToLocalTime(DateTime dateTime) - { - return dateTime + LocalUtcOffset; - } -} - diff --git a/SnapX.Core/Utils/Miscellaneous/StringLineReader.cs b/SnapX.Core/Utils/Miscellaneous/StringLineReader.cs deleted file mode 100644 index 025d63774..000000000 --- a/SnapX.Core/Utils/Miscellaneous/StringLineReader.cs +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - - -using System.Text; - -namespace SnapX.Core.Utils.Miscellaneous; - -public class StringLineReader -{ - public string Text { get; private set; } - public int Position { get; private set; } - public int Length { get; private set; } - - public StringLineReader(string text) - { - Text = text; - Length = Text.Length; - } - - public string ReadLine() - { - var builder = new StringBuilder(); - - while (!string.IsNullOrEmpty(Text) && Position < Length) - { - var ch = Text[Position]; - builder.Append(ch); - Position++; - - if (ch != '\r' && ch != '\n' && Position != Length) - { - return builder.ToString(); - } - - if (ch == '\r' && Position < Length && Text[Position] == '\n') - { - continue; - } - - return builder.ToString(); - } - - return null; - } - - public string[] ReadAllLines(bool autoTrim = true) - { - List lines = []; - - string line; - - while ((line = ReadLine()) != null) - { - if (autoTrim) line = line.Trim(); - lines.Add(line); - } - - return lines.ToArray(); - } - - public void Reset() - { - Position = 0; - } -} - From b4081171c4106f606d5aeef3ad53f3d0e1971839 Mon Sep 17 00:00:00 2001 From: Brycen G Date: Thu, 17 Jul 2025 15:37:22 -0400 Subject: [PATCH 20/31] style: fix nullability warnings and styling issues --- SnapX.Avalonia/App.axaml.cs | 22 +- .../ViewModels/HomePageViewModel.cs | 93 +++---- SnapX.CommonUI/Changelog.cs | 30 +-- SnapX.CommonUI/Types/CommitTypes.cs | 16 +- SnapX.CommonUI/Types/TagTypes.cs | 2 +- .../ViewModels/AboutWindowViewModel.cs | 68 ++--- SnapX.Core/History/HistoryItem.cs | 72 ++++- SnapX.Core/Job/TaskInfo.cs | 2 +- SnapX.Core/Job/WorkerTask.cs | 65 ++--- SnapX.Core/Utils/DNS/AdapterInfo.cs | 21 +- SnapX.Core/Utils/DNS/DNSInfo.cs | 15 +- SnapX.Core/Utils/Miscellaneous/FPSManager.cs | 55 ++-- SnapX.Core/Utils/Native/LinuxAPI.cs | 2 +- SnapX.Core/Utils/Parsers/CodeMenuEntry.cs | 13 +- .../Utils/Parsers/CodeMenuEntryActions.cs | 6 +- .../Utils/Parsers/CodeMenuEntryFilename.cs | 7 +- .../Utils/Parsers/CodeMenuEntryPixelInfo.cs | 6 +- SnapX.Core/Utils/Parsers/NameParser.cs | 9 +- SnapX.Core/Utils/Random/RandomCrypto.cs | 4 +- SnapX.Core/Utils/Random/RandomFast.cs | 4 +- SnapX.Core/Utils/WebHelpers.cs | 25 +- SnapX.Core/Watch/WatchFolder.cs | 253 +++++++++++++----- SnapX.Core/Watch/WatchFolderManager.cs | 57 ++-- 23 files changed, 452 insertions(+), 395 deletions(-) diff --git a/SnapX.Avalonia/App.axaml.cs b/SnapX.Avalonia/App.axaml.cs index e21e602ae..41a9f0c63 100644 --- a/SnapX.Avalonia/App.axaml.cs +++ b/SnapX.Avalonia/App.axaml.cs @@ -19,7 +19,7 @@ namespace SnapX.Avalonia; -public partial class App : Application +public class App : Application { public App() { @@ -36,10 +36,10 @@ public override void Initialize() AvaloniaXamlLoader.Load(this); AppDomain.CurrentDomain.UnhandledException += (_, Args) => { - ShowErrorDialog(Lang.UnhandledException, Args.ExceptionObject as Exception); + ShowErrorDialog(Lang.UnhandledException, (Args.ExceptionObject as Exception)!); }; #if DEBUG - Current.AttachDevTools(); + Current?.AttachDevTools(); #endif // Default logic doesn't auto-detect windows theme anymore in designer @@ -92,7 +92,7 @@ private void ShowErrorDialog(string? title, Exception ex) // Padding = new Thickness(10), }); } - var version = Assembly.GetExecutingAssembly().GetName().Version; + var version = Assembly.GetExecutingAssembly().GetName().Version!; var semver = version.Major + "." + version.Minor + "." + version.Revision; stackPanel.Children.Add(new SelectableTextBlock { @@ -117,7 +117,7 @@ private void ShowErrorDialog(string? title, Exception ex) FontWeight = FontWeight.Bold, CornerRadius = new CornerRadius(5) }; - reportButton.Click += (sender, e) => OnReportErrorClicked(); + reportButton.Click += (_, _) => OnReportErrorClicked(); var githubButton = new Button { @@ -133,7 +133,7 @@ private void ShowErrorDialog(string? title, Exception ex) FontWeight = FontWeight.Bold, CornerRadius = new CornerRadius(5) }; - githubButton.Click += (sender, e) => OnGitHubButtonClicked(ex); + githubButton.Click += (_, _) => OnGitHubButtonClicked(ex); var copyButton = new Button @@ -152,7 +152,7 @@ private void ShowErrorDialog(string? title, Exception ex) }; // Copy error to clipboard when clicked - copyButton.Click += (sender, e) => CopyErrorToClipboard(ex.ToString()); + copyButton.Click += (_, _) => CopyErrorToClipboard(ex.ToString()); buttonPanel.Children.Add(reportButton); @@ -195,14 +195,14 @@ private void OnReportErrorClicked() { // For now, do nothing when the button is clicked // This is where Sentry comes in - Console.WriteLine("Report Error button clicked. No action yet. If you have telemetry enabled, (it is by default) it will have already been sent to Sentry."); + DebugHelper.WriteLine("Report Error button clicked. No action yet. If you have telemetry enabled, (it is by default) it will have already been sent to Sentry."); } public static void Shutdown() { try { - SnapX?.shutdown(); + SnapX.shutdown(); } catch (Exception e) { @@ -279,7 +279,7 @@ public override void OnFrameworkInitializationCompleted() tray.display(); break; } - case ISingleViewApplicationLifetime singleView when SnapX.isSilent(): + case ISingleViewApplicationLifetime when SnapX.isSilent(): return; case ISingleViewApplicationLifetime singleView: { @@ -327,7 +327,7 @@ public static void CreateAboutWindowStatic() aboutWindow.Show(); } } - public void NativeMenuAboutSnapXClick(object? Sender, EventArgs E) + public void NativeMenuAboutSnapXClick(object? _, EventArgs E) { CreateAboutWindowStatic(); } diff --git a/SnapX.Avalonia/ViewModels/HomePageViewModel.cs b/SnapX.Avalonia/ViewModels/HomePageViewModel.cs index deed41fae..17160db7d 100644 --- a/SnapX.Avalonia/ViewModels/HomePageViewModel.cs +++ b/SnapX.Avalonia/ViewModels/HomePageViewModel.cs @@ -17,25 +17,14 @@ namespace SnapX.Avalonia.ViewModels; public partial class HomePageViewModel : ViewModelBase { public AvaloniaList SelectedTasks { get; set; } = []; - public AvaloniaList recentTasks { get; set; } = - []; - private System.Timers.Timer _refreshTimer; - private bool _isRefreshing; // Guard flag to prevent concurrent refreshes + public AvaloniaList recentTasks { get; set; } = []; + private readonly System.Timers.Timer _refreshTimer = new(5000); // Refresh every 5 seconds + private bool _isRefreshing; private int _failedRefreshTasks; - private DateTime _lastCacheTime = DateTime.MinValue; - private List _cachedTasks; - private readonly TimeSpan _cacheDuration = TimeSpan.FromSeconds(4); - public void InvalidateCache() { - _lastCacheTime = DateTime.MinValue; - _cachedTasks = []; - } - public HomePageViewModel() - { - // ShowContextMenuCommand = new RelayCommand(ShowContextMenu); - _refreshTimer = new System.Timers.Timer(5000); // Refresh every 5 seconds } + // ShowContextMenuCommand = new RelayCommand(ShowContextMenu); public async Task Initialize() { @@ -49,34 +38,40 @@ public async Task Initialize() public void StartTimer() => _refreshTimer.Start(); private async void OnRefreshTimerElapsed(object sender, ElapsedEventArgs e) { - if (_isRefreshing) - { - DebugHelper.WriteLine("Previous timer run already in progress. Skipping this timer tick."); - // Apply more conservative _refreshTimer interval when we know that there's a bunch of tasks. - if (recentTasks.Count > 3000) _refreshTimer.Interval = 10_000; - if (_failedRefreshTasks > 15) _refreshTimer.Interval = 30_000; - if (_failedRefreshTasks > 10) _refreshTimer.Interval = 20_000; - if (_failedRefreshTasks > 5) _refreshTimer.Interval = 10_000; - if (_failedRefreshTasks > 19) _refreshTimer.Interval = 60_000; - // Fuck it, give up. - if (_failedRefreshTasks > 20) _refreshTimer.Stop(); - _failedRefreshTasks++; - return; - } - - _isRefreshing = true; try { - // ConfigureAwait(false) is good practice here as it's background work. - await RefreshTasks().ConfigureAwait(false); + if (_isRefreshing) + { + DebugHelper.WriteLine("Previous timer run already in progress. Skipping this timer tick."); + // Apply more conservative _refreshTimer interval when we know that there's a bunch of tasks. + if (recentTasks.Count > 3000) _refreshTimer.Interval = 10_000; + if (_failedRefreshTasks > 15) _refreshTimer.Interval = 30_000; + if (_failedRefreshTasks > 10) _refreshTimer.Interval = 20_000; + if (_failedRefreshTasks > 5) _refreshTimer.Interval = 10_000; + if (_failedRefreshTasks > 19) _refreshTimer.Interval = 60_000; + // Fuck it, give up. + if (_failedRefreshTasks > 20) _refreshTimer.Stop(); + _failedRefreshTasks++; + return; + } + + _isRefreshing = true; + try + { + await RefreshTasks().ConfigureAwait(false); + } + catch (Exception ex) + { + DebugHelper.WriteException(ex); + } + finally + { + _isRefreshing = false; + } } catch (Exception ex) { - DebugHelper.WriteException(ex); - } - finally - { - _isRefreshing = false; // Reset the flag when the refresh is complete (or fails) + DebugHelper.WriteException(ex, "Error while refreshing tasks"); } } [RelayCommand] @@ -206,27 +201,14 @@ public async Task RefreshTasks() { var typeofVM = typeof(HomePageViewModel); - List newDesiredTasks; - - // Check cache first - if (DateTime.Now - _lastCacheTime < _cacheDuration) - { - newDesiredTasks = _cachedTasks; - } - else - { - var historyItems = await TaskManager.History.GetHistoryItemsAsync(30_000).ConfigureAwait(false); + var historyItems = await TaskManager.History.GetHistoryItemsAsync().ConfigureAwait(false); var tasks = historyItems.Select(task => new ListTaskTemplate(typeofVM, task)); - newDesiredTasks = tasks + var newDesiredTasks = tasks .OrderByDescending(item => item.task.Id) .ToList(); - - _cachedTasks = newDesiredTasks; - _lastCacheTime = DateTime.Now; - } - + await Task.Yield(); await Dispatcher.UIThread.InvokeAsync(() => { if (newDesiredTasks.Count > 50_000) @@ -244,6 +226,7 @@ await Dispatcher.UIThread.InvokeAsync(() => { if (!newDesiredTaskIds.Contains(recentTasks[i].task.Id)) { + DebugHelper.WriteLine($"Removing {recentTasks[i].task.Id}"); recentTasks.RemoveAt(i); } } @@ -257,6 +240,8 @@ await Dispatcher.UIThread.InvokeAsync(() => continue; } var index = recentTasks.IndexOf(existingItem); + DebugHelper.WriteLine($"Replacing {index}"); + if (index == -1) continue; recentTasks.RemoveAt(index); recentTasks.Insert(index, newItem); diff --git a/SnapX.CommonUI/Changelog.cs b/SnapX.CommonUI/Changelog.cs index 3e39940f0..a7f7fcbad 100644 --- a/SnapX.CommonUI/Changelog.cs +++ b/SnapX.CommonUI/Changelog.cs @@ -21,17 +21,18 @@ internal partial class ChangelogContext : JsonSerializerContext; public abstract class Changelog { private static readonly HttpClient Client = HttpClientFactory.Get(); - public string Version { get; init; } - public Version versionSemver; - public int major; - public int minor; - public int patch; + protected string Version { get; init; } + private readonly Version versionSemver; + private readonly int major; + private readonly int minor; + private readonly int patch; - public JsonSerializerOptions Options = new() + private readonly JsonSerializerOptions Options = new() { TypeInfoResolver = ChangelogContext.Default }; - public Changelog(string version) + + protected Changelog(string version) { Version = version; versionSemver = new Version(version); @@ -42,8 +43,8 @@ public Changelog(string version) public record ChangelogVersion { - public string Version { get; set; } - public string Content { get; set; } + public string Version { get; set; } = "0.0.0"; + public string Content { get; set; } = ""; } public virtual async Task GetChangeSummary() { @@ -78,7 +79,7 @@ private bool IsValidChangelog(string changelog) return false; } #if DEBUG - DebugHelper.WriteLine($"Validating changelog: {changelog?.Substring(0, Math.Min(100, changelog.Length))}..."); + DebugHelper.WriteLine($"Validating changelog: {changelog[..Math.Min(100, changelog.Length)]}..."); #endif return changelog!.Length > 4; } @@ -158,7 +159,7 @@ private async Task GetTagsSinceVersion() }) .Select(tag => { - var firstLineOfMessage = tag.Commit?.Message?.Split('\n').FirstOrDefault()?.Trim(); + var firstLineOfMessage = tag.Commit?.Message.Split('\n').FirstOrDefault()?.Trim(); return $"Tag: {tag.Name} - {firstLineOfMessage}"; }) .ToList(); @@ -180,7 +181,7 @@ private async Task GetBuildSummaryFromActions() return string.Empty; var buildSummaries = actions.WorkflowRuns - .Where(run => (run?.RunNumber > patch) && (run.Name.Contains("build", StringComparison.OrdinalIgnoreCase)) && run.Status.Contains("success", StringComparison.InvariantCultureIgnoreCase)) + .Where(run => run.RunNumber > patch && (run.Name.Contains("build", StringComparison.OrdinalIgnoreCase)) && run.Status.Contains("success", StringComparison.InvariantCultureIgnoreCase)) .Select(run => $"{run.Name} #{run.RunNumber}: {run.DisplayTitle} - {run.Actor.Login}") .ToList(); @@ -234,13 +235,12 @@ private async Task GetRecentCommits() /// Defaults to splitting on two or more consecutive newline sequences. /// /// An enumerable of individual changelog entries. - /// Thrown if changelogs is null. + /// Thrown if changelogs are null. public static IEnumerable SeparateChangelogEntries( IEnumerable changelogs, string? pattern = null) { - if (changelogs == null) - throw new ArgumentNullException(nameof(changelogs)); + ArgumentNullException.ThrowIfNull(changelogs); // Default pattern for separating traditional multi-line changelog entries pattern ??= @"(?:\r?\n){2,}"; diff --git a/SnapX.CommonUI/Types/CommitTypes.cs b/SnapX.CommonUI/Types/CommitTypes.cs index 7a6375af0..988643902 100644 --- a/SnapX.CommonUI/Types/CommitTypes.cs +++ b/SnapX.CommonUI/Types/CommitTypes.cs @@ -32,13 +32,13 @@ public record Author( ); public record Commit( - [property: JsonPropertyName("author")] Author Author, - [property: JsonPropertyName("committer")] Committer Committer, + [property: JsonPropertyName("author")] Author? Author, + [property: JsonPropertyName("committer")] Committer? Committer, [property: JsonPropertyName("message")] string Message, - [property: JsonPropertyName("tree")] Tree Tree, + [property: JsonPropertyName("tree")] Tree? Tree, [property: JsonPropertyName("html_url")] string Url, [property: JsonPropertyName("comment_count")] int? CommentCount, - [property: JsonPropertyName("verification")] Verification Verification + [property: JsonPropertyName("verification")] Verification? Verification ); public record Committer( @@ -75,13 +75,13 @@ public record Parent( public record Root( [property: JsonPropertyName("sha")] string Sha, [property: JsonPropertyName("node_id")] string NodeId, - [property: JsonPropertyName("commit")] Commit Commit, + [property: JsonPropertyName("commit")] Commit? Commit, [property: JsonPropertyName("url")] string Url, [property: JsonPropertyName("html_url")] string HtmlUrl, [property: JsonPropertyName("comments_url")] string CommentsUrl, - [property: JsonPropertyName("author")] Author Author, - [property: JsonPropertyName("committer")] Committer Committer, - [property: JsonPropertyName("parents")] IReadOnlyList Parents + [property: JsonPropertyName("author")] Author? Author, + [property: JsonPropertyName("committer")] Committer? Committer, + [property: JsonPropertyName("parents")] IReadOnlyList? Parents ); diff --git a/SnapX.CommonUI/Types/TagTypes.cs b/SnapX.CommonUI/Types/TagTypes.cs index f14e3b71b..b28547f72 100644 --- a/SnapX.CommonUI/Types/TagTypes.cs +++ b/SnapX.CommonUI/Types/TagTypes.cs @@ -8,6 +8,6 @@ public record Tag( [property: JsonPropertyName("name")] string Name, [property: JsonPropertyName("zipball_url")] string ZipballUrl, [property: JsonPropertyName("tarball_url")] string TarballUrl, - [property: JsonPropertyName("commit")] Commit Commit, + [property: JsonPropertyName("commit")] Commit? Commit, [property: JsonPropertyName("node_id")] string NodeId ); diff --git a/SnapX.CommonUI/ViewModels/AboutWindowViewModel.cs b/SnapX.CommonUI/ViewModels/AboutWindowViewModel.cs index 559b1bfc0..0382d98a9 100644 --- a/SnapX.CommonUI/ViewModels/AboutWindowViewModel.cs +++ b/SnapX.CommonUI/ViewModels/AboutWindowViewModel.cs @@ -9,7 +9,7 @@ namespace SnapX.CommonUI.ViewModels; public partial class AboutWindowViewModel : ViewModelBase { // Internal instance of the base class (SnapX.CommonUI.AboutDialog) - private AboutDialog _commonAboutDialog = new(); + private readonly AboutDialog _commonAboutDialog = new(); [UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", @@ -21,6 +21,7 @@ private Task InitDataAsync() LoadedAssemblies = string.Join(Environment.NewLine, combinedLoadedAssemblies .Where(a => a.GetName().Name != null) .Where(a => +#pragma warning disable CS8602 // Dereference of a possibly null reference. !a.GetName().Name.StartsWith("System") && !a.GetName().Name.StartsWith("SnapX", StringComparison.OrdinalIgnoreCase) && !a.GetName().Name.StartsWith("Anonymous", StringComparison.OrdinalIgnoreCase) && @@ -37,8 +38,10 @@ private Task InitDataAsync() .Select(g => g.Count() > 1 ? $"{g.Key} {g.First().Version.Major}.{g.First().Version.Minor}.{g.First().Version.Build}" : $"{g.First().Name} {g.First().Version.Major}.{g.First().Version.Minor}.{g.First().Version.Build}") - .Append($"SQLite {Core.SnapX.DbConnection.ServerVersion}") + .Append($"SQLite {Core.SnapX.DbConnection?.ServerVersion}") .OrderBy(name => name)); +#pragma warning restore CS8602 // Dereference of a possibly null reference. + Description = _commonAboutDialog.GetDescription(); Version = _commonAboutDialog.GetVersion(); Copyright = _commonAboutDialog.GetCopyright(); @@ -56,48 +59,21 @@ private Task InitDataAsync() SystemInformationText = $"{SystemInfo} ({OsArchitecture}, {OsPlatform}) powered by {Runtime}!"; return Task.CompletedTask; } - [ObservableProperty] - public string dialogTitle = Lang.AboutSnapX; - [ObservableProperty] - private string? description; - [ObservableProperty] - public string? buildInformation; - [ObservableProperty] - - public string? version; - [ObservableProperty] - public string? copyright; - [ObservableProperty] - - public string? license; - [ObservableProperty] - - public string? website; - [ObservableProperty] - - public string? systemInfo; - [ObservableProperty] - - public string? osArchitecture; - [ObservableProperty] - - public string? runtime; - [ObservableProperty] - - public string? osPlatform; - [ObservableProperty] - - public string? documentation; - [ObservableProperty] - - public string? issues; - [ObservableProperty] - public string? discord; - [ObservableProperty] - public string? donate; - [ObservableProperty] - public string? loadedAssemblies; - - [ObservableProperty] - public string? systemInformationText; + [ObservableProperty] private string dialogTitle = Lang.AboutSnapX; + [ObservableProperty] private string? description; + [ObservableProperty] private string? buildInformation; + [ObservableProperty] private string? version; + [ObservableProperty] private string? copyright; + [ObservableProperty] private string? license; + [ObservableProperty] private string? website; + [ObservableProperty] private string? systemInfo; + [ObservableProperty] private string? osArchitecture; + [ObservableProperty] private string? runtime; + [ObservableProperty] private string? osPlatform; + [ObservableProperty] private string? documentation; + [ObservableProperty] private string? issues; + [ObservableProperty] private string? discord; + [ObservableProperty] private string? donate; + [ObservableProperty] private string? loadedAssemblies; + [ObservableProperty] private string? systemInformationText; } diff --git a/SnapX.Core/History/HistoryItem.cs b/SnapX.Core/History/HistoryItem.cs index a5ddde2a9..9a2c28391 100644 --- a/SnapX.Core/History/HistoryItem.cs +++ b/SnapX.Core/History/HistoryItem.cs @@ -33,10 +33,23 @@ public record Tag { public int Id { get; set; } public required string Name { get; set; } - public string Value { get; set; } = ""; + + public virtual bool Equals(Tag? other) + { + if (other is null) return false; + if (ReferenceEquals(this, other)) return true; + return Id == other.Id && + Name == other.Name && + Value == other.Value; + } + + public override int GetHashCode() + { + return HashCode.Combine(Id, Name, Value); + } } - public List? Tags { get; set; } = []; + public List? Tags = []; public override string ToString() { var text = ""; @@ -71,5 +84,60 @@ public string TrayMenuText !string.IsNullOrWhiteSpace(FilePath) && File.Exists(FilePath) ? FilePath : URL ?? ThumbnailURL; + public virtual bool Equals(HistoryItem? other) + { + if (other is null) return false; + if (ReferenceEquals(this, other)) return true; + + return FileName == other.FileName && + FilePath == other.FilePath && + DateTime == other.DateTime && + Type == other.Type && + Id == other.Id && + Hidden == other.Hidden && + Host == other.Host && + URL == other.URL && + ThumbnailURL == other.ThumbnailURL && + DeletionURL == other.DeletionURL && + ShortenedURL == other.ShortenedURL && + TagsEqual(Tags, other.Tags); + } + + private static bool TagsEqual(List? a, List? b) + { + if (a is null && b is null) return true; + if (a is null || b is null) return false; + if (a.Count != b.Count) return false; + + var orderedA = a.OrderBy(t => t.Id).ThenBy(t => t.Name).ThenBy(t => t.Value); + var orderedB = b.OrderBy(t => t.Id).ThenBy(t => t.Name).ThenBy(t => t.Value); + return orderedA.SequenceEqual(orderedB); + } + + public override int GetHashCode() + { + var hash = new HashCode(); + hash.Add(FileName); + hash.Add(FilePath); + hash.Add(DateTime); + hash.Add(Type); + hash.Add(Id); + hash.Add(Hidden); + hash.Add(Host); + hash.Add(URL); + hash.Add(ThumbnailURL); + hash.Add(DeletionURL); + hash.Add(ShortenedURL); + + if (Tags != null) + { + foreach (var tag in Tags.OrderBy(t => t.Id).ThenBy(t => t.Name).ThenBy(t => t.Value)) + { + hash.Add(tag); + } + } + + return hash.ToHashCode(); + } } diff --git a/SnapX.Core/Job/TaskInfo.cs b/SnapX.Core/Job/TaskInfo.cs index 7fa0c250b..9d62270f6 100644 --- a/SnapX.Core/Job/TaskInfo.cs +++ b/SnapX.Core/Job/TaskInfo.cs @@ -125,7 +125,7 @@ public string UploaderHost public Stopwatch UploadDuration { get; set; } - public UploadResult Result { get; set; } + public UploadResult? Result { get; set; } public TaskInfo(TaskSettings? taskSettings = null) { diff --git a/SnapX.Core/Job/WorkerTask.cs b/SnapX.Core/Job/WorkerTask.cs index 328f9e6ba..0ed239b26 100644 --- a/SnapX.Core/Job/WorkerTask.cs +++ b/SnapX.Core/Job/WorkerTask.cs @@ -5,7 +5,6 @@ using System.Text; using System.Text.RegularExpressions; using SixLabors.ImageSharp; -using SixLabors.ImageSharp.PixelFormats; using SnapX.Core.Hotkey; using SnapX.Core.Upload; using SnapX.Core.Upload.BaseServices; @@ -39,13 +38,13 @@ public class WorkerTask : IDisposable public bool StopRequested { get; private set; } public bool RequestSettingUpdate { get; private set; } public bool EarlyURLCopied { get; private set; } - public Stream Data { get; private set; } - public Image Image { get; private set; } + public Stream? Data { get; private set; } + public Image? Image { get; private set; } public bool KeepImage { get; set; } public string? Text { get; private set; } private ThreadWorker threadWorker; - private GenericUploader uploader; + private GenericUploader? uploader; private TaskReferenceHelper taskReferenceHelper; #region Constructors @@ -287,10 +286,10 @@ private void ThreadDoWork() Clipboard.Clear(); } - if ((Info.Job == TaskJob.Job || (Info.Job == TaskJob.FileUpload && Info.TaskSettings.AdvancedSettings.UseAfterCaptureTasksDuringFileUpload)) - && Info.TaskSettings.AfterCaptureJob.HasFlag(AfterCaptureTasks.DeleteFile) && !string.IsNullOrEmpty(Info.FilePath) && System.IO.File.Exists(Info.FilePath)) + if ((Info.Job == TaskJob.Job || (Info.Job == TaskJob.FileUpload && (Info.TaskSettings?.AdvancedSettings.UseAfterCaptureTasksDuringFileUpload ?? true))) + && Info.TaskSettings.AfterCaptureJob.HasFlag(AfterCaptureTasks.DeleteFile) && !string.IsNullOrEmpty(Info.FilePath) && File.Exists(Info.FilePath)) { - System.IO.File.Delete(Info.FilePath); + File.Delete(Info.FilePath); } } @@ -490,10 +489,7 @@ private void AddErrorMessage(UploaderErrorManager errors) private void AddErrorMessage(string? error) { - if (Info.Result == null) - { - Info.Result = new UploadResult(); - } + Info.Result ??= new UploadResult(); Info.Result.Errors.Add(error); } @@ -670,29 +666,24 @@ private void DoFileJobs() { if (Info.TaskSettings.AfterCaptureJob.HasFlag(AfterCaptureTasks.PerformActions) && Info.TaskSettings.ExternalPrograms != null) { - IEnumerable actions = Info.TaskSettings.ExternalPrograms.Where(x => x.IsActive); + var actions = Info.TaskSettings.ExternalPrograms.Where(x => x.IsActive); - if (actions.Count() > 0) + if (actions.Any()) { - bool isFileModified = false; - string? fileName = Info.FileName; + var isFileModified = false; + var fileName = Info.FileName; foreach (ExternalProgram fileAction in actions) { - string? modifiedPath = fileAction.Run(Info.FilePath); + var modifiedPath = fileAction.Run(Info.FilePath); - if (!string.IsNullOrEmpty(modifiedPath)) - { - isFileModified = true; - Info.FilePath = modifiedPath; + if (string.IsNullOrEmpty(modifiedPath)) continue; + isFileModified = true; + Info.FilePath = modifiedPath; - if (Data != null) - { - Data.Dispose(); - } + Data?.Dispose(); - fileAction.DeletePendingInputFile(); - } + fileAction.DeletePendingInputFile(); } if (isFileModified) @@ -790,16 +781,7 @@ private void DoAfterUploadJobs() if (Info.TaskSettings.AfterUploadJob.HasFlag(AfterUploadTasks.CopyURLToClipboard)) { - string? txt; - - if (!string.IsNullOrEmpty(Info.TaskSettings.AdvancedSettings.ClipboardContentFormat)) - { - txt = new UploadInfoParser().Parse(Info, Info.TaskSettings.AdvancedSettings.ClipboardContentFormat); - } - else - { - txt = Info.Result.ToString(); - } + var txt = !string.IsNullOrEmpty(Info.TaskSettings.AdvancedSettings.ClipboardContentFormat) ? new UploadInfoParser().Parse(Info, Info.TaskSettings.AdvancedSettings.ClipboardContentFormat) : Info.Result.ToString(); if (!string.IsNullOrEmpty(txt)) { @@ -809,16 +791,7 @@ private void DoAfterUploadJobs() if (Info.TaskSettings.AfterUploadJob.HasFlag(AfterUploadTasks.OpenURL)) { - string? result; - - if (!string.IsNullOrEmpty(Info.TaskSettings.AdvancedSettings.OpenURLFormat)) - { - result = new UploadInfoParser().Parse(Info, Info.TaskSettings.AdvancedSettings.OpenURLFormat); - } - else - { - result = Info.Result.ToString(); - } + var result = !string.IsNullOrEmpty(Info.TaskSettings.AdvancedSettings.OpenURLFormat) ? new UploadInfoParser().Parse(Info, Info.TaskSettings.AdvancedSettings.OpenURLFormat) : Info.Result.ToString(); URLHelpers.OpenURL(result); } diff --git a/SnapX.Core/Utils/DNS/AdapterInfo.cs b/SnapX.Core/Utils/DNS/AdapterInfo.cs index 27b9de824..54440f6ac 100644 --- a/SnapX.Core/Utils/DNS/AdapterInfo.cs +++ b/SnapX.Core/Utils/DNS/AdapterInfo.cs @@ -4,15 +4,8 @@ namespace SnapX.Core.Utils.DNS; -public class AdapterInfo : IDisposable +public class AdapterInfo(NetworkInterface Adapter) : IDisposable { - private NetworkInterface adapter; - - public AdapterInfo(NetworkInterface adapter) - { - this.adapter = adapter; - } - public static List GetEnabledAdapters() { var adapters = new List(); @@ -27,21 +20,21 @@ public static List GetEnabledAdapters() return adapters; } - public bool IsEnabled() => adapter.OperationalStatus == OperationalStatus.Up; + public bool IsEnabled() => Adapter.OperationalStatus == OperationalStatus.Up; - public string? GetCaption() => adapter.ToString(); + public string? GetCaption() => Adapter.ToString(); - public string GetDescription() => adapter.Description; + public string GetDescription() => Adapter.Description; - public string[] GetDNS() => adapter.GetIPProperties().UnicastAddresses.ToList().Select(x => x.Address.ToString()).ToArray(); + public string[] GetDNS() => Adapter.GetIPProperties().UnicastAddresses.ToList().Select(x => x.Address.ToString()).ToArray(); // TODO: SetDNS needs to be implemented on a per platform basis - public uint SetDNS(string primary, string secondary) => throw new NotImplementedException("SetDNS is not implemented."); + public uint SetDNS(string primary, string? secondary) => throw new NotImplementedException("SetDNS is not implemented."); public uint SetDNSAutomatic() { return SetDNS(null, null); } - public void Dispose() => Console.WriteLine($"Disposed adapter {adapter.Description}"); + public void Dispose() => Console.WriteLine($"Disposed adapter {Adapter.Description}"); public override string ToString() => GetDescription(); } diff --git a/SnapX.Core/Utils/DNS/DNSInfo.cs b/SnapX.Core/Utils/DNS/DNSInfo.cs index fc00cb50b..18678003d 100644 --- a/SnapX.Core/Utils/DNS/DNSInfo.cs +++ b/SnapX.Core/Utils/DNS/DNSInfo.cs @@ -3,18 +3,11 @@ namespace SnapX.Core.Utils.DNS; -public class DNSInfo +public class DNSInfo(string Name, string PrimaryDns, string SecondaryDns) { - public string Name { get; set; } - public string PrimaryDNS { get; set; } - public string SecondaryDNS { get; set; } - - public DNSInfo(string name, string primaryDNS, string secondaryDNS) - { - Name = name; - PrimaryDNS = primaryDNS; - SecondaryDNS = secondaryDNS; - } + public string Name { get; set; } = Name; + public string PrimaryDNS { get; set; } = PrimaryDns; + public string SecondaryDNS { get; set; } = SecondaryDns; public override string ToString() { diff --git a/SnapX.Core/Utils/Miscellaneous/FPSManager.cs b/SnapX.Core/Utils/Miscellaneous/FPSManager.cs index a0e403df0..101be9d61 100644 --- a/SnapX.Core/Utils/Miscellaneous/FPSManager.cs +++ b/SnapX.Core/Utils/Miscellaneous/FPSManager.cs @@ -5,30 +5,19 @@ namespace SnapX.Core.Utils.Miscellaneous; -public class FPSManager +public class FPSManager(int FPSLimit) { public event Action FPSUpdated; public int FPS { get; private set; } - public int FPSLimit { get; set; } private int frameCount; - private Stopwatch fpsTimer, frameTimer; + private readonly Stopwatch fpsTimer = new(); + private readonly Stopwatch frameTimer = new(); - public FPSManager() + private void OnFPSUpdated() { - fpsTimer = new Stopwatch(); - frameTimer = new Stopwatch(); - } - - public FPSManager(int fpsLimit) : this() - { - FPSLimit = fpsLimit; - } - - protected void OnFPSUpdated() - { - FPSUpdated?.Invoke(); + FPSUpdated.Invoke(); } public void Update() @@ -38,7 +27,7 @@ public void Update() if (!fpsTimer.IsRunning) fpsTimer.Start(); else if (fpsTimer.ElapsedMilliseconds >= 1000) { - FPS = (int)System.Math.Round(frameCount / fpsTimer.Elapsed.TotalSeconds); + FPS = (int)Math.Round(frameCount / fpsTimer.Elapsed.TotalSeconds); OnFPSUpdated(); @@ -46,29 +35,27 @@ public void Update() fpsTimer.Restart(); } - if (FPSLimit > 0) + if (FPSLimit <= 0) return; + if (!frameTimer.IsRunning) { - if (!frameTimer.IsRunning) - { - frameTimer.Start(); - } - else + frameTimer.Start(); + } + else + { + var currentFrameDuration = frameTimer.Elapsed.TotalMilliseconds; + var targetFrameDuration = 1000d / FPSLimit; + + if (currentFrameDuration < targetFrameDuration) { - double currentFrameDuration = frameTimer.Elapsed.TotalMilliseconds; - double targetFrameDuration = 1000d / FPSLimit; + var sleepDuration = (int)Math.Round(targetFrameDuration - currentFrameDuration); - if (currentFrameDuration < targetFrameDuration) + if (sleepDuration > 0) { - int sleepDuration = (int)System.Math.Round(targetFrameDuration - currentFrameDuration); - - if (sleepDuration > 0) - { - Thread.Sleep(sleepDuration); - } + Thread.Sleep(sleepDuration); } - - frameTimer.Restart(); } + + frameTimer.Restart(); } } } diff --git a/SnapX.Core/Utils/Native/LinuxAPI.cs b/SnapX.Core/Utils/Native/LinuxAPI.cs index 6539fb8b2..a6e211cfd 100644 --- a/SnapX.Core/Utils/Native/LinuxAPI.cs +++ b/SnapX.Core/Utils/Native/LinuxAPI.cs @@ -5,7 +5,7 @@ using SixLabors.ImageSharp.PixelFormats; using SnapX.Core.Interfaces; using SnapX.Core.Media; -using WaylandSharp; +using WaylandSharper; namespace SnapX.Core.Utils.Native; diff --git a/SnapX.Core/Utils/Parsers/CodeMenuEntry.cs b/SnapX.Core/Utils/Parsers/CodeMenuEntry.cs index 3939da54f..666be06a8 100644 --- a/SnapX.Core/Utils/Parsers/CodeMenuEntry.cs +++ b/SnapX.Core/Utils/Parsers/CodeMenuEntry.cs @@ -2,21 +2,10 @@ namespace SnapX.Core.Utils.Parsers; -public abstract class CodeMenuEntry +public abstract class CodeMenuEntry(string Value, string Description, string? Category = null) { protected abstract string Prefix { get; } - public string Value { get; private set; } - public string Description { get; private set; } - public string Category { get; private set; } - - public CodeMenuEntry(string value, string description, string category = null) - { - Value = value; - Description = description; - Category = category; - } - public string ToPrefixString() { return ToPrefixString(Prefix); diff --git a/SnapX.Core/Utils/Parsers/CodeMenuEntryActions.cs b/SnapX.Core/Utils/Parsers/CodeMenuEntryActions.cs index ca9bf211a..38a28eda2 100644 --- a/SnapX.Core/Utils/Parsers/CodeMenuEntryActions.cs +++ b/SnapX.Core/Utils/Parsers/CodeMenuEntryActions.cs @@ -1,16 +1,12 @@ namespace SnapX.Core.Utils.Parsers; -public class CodeMenuEntryActions : CodeMenuEntry +public class CodeMenuEntryActions(string Value, string Description) : CodeMenuEntry(Value, Description) { protected override string Prefix { get; } = "$"; public static readonly CodeMenuEntryActions input = new("input", "File path"); public static readonly CodeMenuEntryActions output = new("output", "File path with output file name extension"); - public CodeMenuEntryActions(string value, string description) : base(value, description) - { - } - public static string Parse(string pattern, string inputPath, string outputPath) { var result = pattern; diff --git a/SnapX.Core/Utils/Parsers/CodeMenuEntryFilename.cs b/SnapX.Core/Utils/Parsers/CodeMenuEntryFilename.cs index 549d13506..9507f9990 100644 --- a/SnapX.Core/Utils/Parsers/CodeMenuEntryFilename.cs +++ b/SnapX.Core/Utils/Parsers/CodeMenuEntryFilename.cs @@ -1,6 +1,7 @@ namespace SnapX.Core.Utils.Parsers; -public class CodeMenuEntryFilename : CodeMenuEntry +public class CodeMenuEntryFilename(string Value, string Description, string Category = null) + : CodeMenuEntry(Value, Description, Category) { protected override string Prefix => "%"; @@ -38,9 +39,5 @@ public class CodeMenuEntryFilename : CodeMenuEntry public static readonly CodeMenuEntryFilename uln = new("uln", "User login name", "Computer"); public static readonly CodeMenuEntryFilename cn = new("cn", "Computer name/HOSTNAME", "Computer"); public static readonly CodeMenuEntryFilename n = new("n", "New line"); - - public CodeMenuEntryFilename(string value, string description, string category = null) : base(value, description, category) - { - } } diff --git a/SnapX.Core/Utils/Parsers/CodeMenuEntryPixelInfo.cs b/SnapX.Core/Utils/Parsers/CodeMenuEntryPixelInfo.cs index b93c80135..ddb552dbd 100644 --- a/SnapX.Core/Utils/Parsers/CodeMenuEntryPixelInfo.cs +++ b/SnapX.Core/Utils/Parsers/CodeMenuEntryPixelInfo.cs @@ -4,7 +4,7 @@ namespace SnapX.Core.Utils.Parsers; -public class CodeMenuEntryPixelInfo : CodeMenuEntry +public class CodeMenuEntryPixelInfo(string Value, string Description) : CodeMenuEntry(Value, Description) { protected override string Prefix { get; } = "$"; @@ -36,10 +36,6 @@ public class CodeMenuEntryPixelInfo : CodeMenuEntry public static readonly CodeMenuEntryPixelInfo y = new("y", "Y position"); public static readonly CodeMenuEntryPixelInfo n = new("n", "New line"); - public CodeMenuEntryPixelInfo(string value, string description) : base(value, description) - { - } - public static string Parse(string input, Rgba64 color, Point position) { input = input.Replace(r255.ToPrefixString(), color.R.ToString(), StringComparison.InvariantCultureIgnoreCase). diff --git a/SnapX.Core/Utils/Parsers/NameParser.cs b/SnapX.Core/Utils/Parsers/NameParser.cs index a84be9f87..491cd1d10 100644 --- a/SnapX.Core/Utils/Parsers/NameParser.cs +++ b/SnapX.Core/Utils/Parsers/NameParser.cs @@ -107,14 +107,7 @@ public NameParser(NameParserType nameParserType) string hour; - if (sb.ToString().Contains(CodeMenuEntryFilename.pm.ToPrefixString())) - { - hour = Helpers.HourTo12(dt.Hour); - } - else - { - hour = Helpers.AddZeroes(dt.Hour); - } + hour = sb.ToString().Contains(CodeMenuEntryFilename.pm.ToPrefixString()) ? Helpers.HourTo12(dt.Hour) : Helpers.AddZeroes(dt.Hour); sb.Replace(CodeMenuEntryFilename.h.ToPrefixString(), hour) .Replace(CodeMenuEntryFilename.mi.ToPrefixString(), Helpers.AddZeroes(dt.Minute)) diff --git a/SnapX.Core/Utils/Random/RandomCrypto.cs b/SnapX.Core/Utils/Random/RandomCrypto.cs index 86dac8e4b..55868a70c 100644 --- a/SnapX.Core/Utils/Random/RandomCrypto.cs +++ b/SnapX.Core/Utils/Random/RandomCrypto.cs @@ -8,8 +8,8 @@ namespace SnapX.Core.Utils.Random; // https://docs.microsoft.com/en-us/archive/msdn-magazine/2007/september/net-matters-tales-from-the-cryptorandom public static class RandomCrypto { - private static readonly object randomLock = new object(); - private static byte[] uint32Buffer = new byte[4]; + private static readonly Lock randomLock = new(); + private static readonly byte[] uint32Buffer = new byte[4]; /// Returns a non-negative random integer. /// A 32-bit signed integer that is greater than or equal to 0 and less than System.Int32.MaxValue. diff --git a/SnapX.Core/Utils/Random/RandomFast.cs b/SnapX.Core/Utils/Random/RandomFast.cs index 901df0c44..563e8c000 100644 --- a/SnapX.Core/Utils/Random/RandomFast.cs +++ b/SnapX.Core/Utils/Random/RandomFast.cs @@ -5,8 +5,8 @@ namespace SnapX.Core.Utils.Random; public static class RandomFast { - private static readonly object randomLock = new object(); - private static readonly System.Random random = new System.Random(); + private static readonly Lock randomLock = new(); + private static readonly System.Random random = new(); /// Returns a non-negative random integer. /// A 32-bit signed integer that is greater than or equal to 0 and less than System.Int32.MaxValue. diff --git a/SnapX.Core/Utils/WebHelpers.cs b/SnapX.Core/Utils/WebHelpers.cs index 0a6ba1b9e..d0891b3b9 100644 --- a/SnapX.Core/Utils/WebHelpers.cs +++ b/SnapX.Core/Utils/WebHelpers.cs @@ -25,7 +25,7 @@ public static async Task DownloadFileAsync(string url, string? filePath) if (!responseMessage.IsSuccessStatusCode) { - DebugHelper.Logger.Error("{url}: {responseMessage.ReasonPhrase}", url, responseMessage); + DebugHelper.Logger?.Error("{Url}: {ResponseMessageReasonPhrase}", url, responseMessage); return; } @@ -54,14 +54,14 @@ public static async Task DataURLToImage(string? url) var base64Data = match.Groups["data"].Value; - byte[] imageBytes = Convert.FromBase64String(base64Data); + var imageBytes = Convert.FromBase64String(base64Data); using var ms = new MemoryStream(imageBytes); var image = await Image.LoadAsync(ms); return image; } - public static async Task DownloadStringAsync(string url) + public static async Task DownloadStringAsync(string url) { if (string.IsNullOrEmpty(url)) { @@ -70,13 +70,10 @@ public static async Task DownloadStringAsync(string url) var client = HttpClientFactory.Get(); using var responseMessage = await client.GetAsync(url); - if (!responseMessage.IsSuccessStatusCode) - { - DebugHelper.Logger.Error("{url}: {responseMessage.ReasonPhrase}", url, responseMessage); - return null; - } + if (responseMessage.IsSuccessStatusCode) return await responseMessage.Content.ReadAsStringAsync(); + DebugHelper.Logger?.Error("{Url}: {ResponseMessageReasonPhrase}", url, responseMessage); + return null; - return await responseMessage.Content.ReadAsStringAsync(); } @@ -94,7 +91,7 @@ public static async Task DownloadStringAsync(string url) } - public static async Task DownloadImageAsync(string? url) + public static async Task DownloadImageAsync(string? url) { if (string.IsNullOrEmpty(url)) return null; @@ -108,13 +105,13 @@ public static async Task DownloadImageAsync(string? url) return null; } - var mediaType = responseMessage.Content.Headers.ContentType.MediaType; + var mediaType = responseMessage.Content.Headers.ContentType?.MediaType; if (mediaType == null) { - DebugHelper.Logger.Error("{url}: mediaType is null.", url); + DebugHelper.Logger?.Error("{Url}: mediaType is null", url); return null; } - if (!MimeTypesPlus.IsImageMimeType(mediaType)) + if (!mediaType.Contains("image/")) return null; var data = await responseMessage.Content.ReadAsByteArrayAsync(); @@ -126,7 +123,7 @@ public static async Task DownloadImageAsync(string? url) } catch (Exception ex) { - DebugHelper.Logger.Error("{url}: {message}", url, ex.Message); + DebugHelper.Logger?.Error("{Url}: {Message}", url, ex.Message); DebugHelper.WriteException(ex); return null; } diff --git a/SnapX.Core/Watch/WatchFolder.cs b/SnapX.Core/Watch/WatchFolder.cs index d377c5b84..7767f95b9 100644 --- a/SnapX.Core/Watch/WatchFolder.cs +++ b/SnapX.Core/Watch/WatchFolder.cs @@ -2,138 +2,263 @@ using System.Diagnostics; +using Microsoft.Extensions.FileProviders; using SnapX.Core.Job; using SnapX.Core.Utils; namespace SnapX.Core.Watch; -public class WatchFolder : IDisposable +public sealed class WatchFolder : IDisposable { - public WatchFolderSettings Settings { get; set; } - public TaskSettings? TaskSettings { get; set; } + public WatchFolderSettings? Settings { get; set; } + public TaskSettings? TaskSettings { get; set; } // Assuming this is for other task-related settings public delegate void FileWatcherTriggerEventHandler(string? path); + public event FileWatcherTriggerEventHandler? FileWatcherTrigger; - public event FileWatcherTriggerEventHandler FileWatcherTrigger; + private SynchronizationContext _context; + private FileSystemWatcher? _fileSystemWatcher; + private List _timers = []; + private PhysicalFileProvider? _fileProvider; - private SynchronizationContext context; - private FileSystemWatcher fileWatcher; - private List timers = []; - - public virtual void Enable() + /// + /// Enables the file watcher. + /// + public void Enable() { Dispose(); - string? folderPath = FileHelpers.ExpandFolderVariables(Settings.FolderPath); + if (Settings == null) + { + DebugHelper.WriteLine("WatchFolder settings are not configured."); + return; + } + + var folderPath = FileHelpers.ExpandFolderVariables(Settings.FolderPath); + + if (string.IsNullOrEmpty(folderPath) || !Directory.Exists(folderPath)) + { + DebugHelper.WriteLine($"Invalid or non-existent folder path: {folderPath}"); + return; + } + + _context = SynchronizationContext.Current ?? new SynchronizationContext(); - if (!string.IsNullOrEmpty(folderPath) && Directory.Exists(folderPath)) + try { - context = SynchronizationContext.Current ?? new SynchronizationContext(); + _fileSystemWatcher = new FileSystemWatcher(folderPath); + if (!string.IsNullOrEmpty(Settings.Filter)) + { + _fileSystemWatcher.Filter = Settings.Filter; + } + _fileSystemWatcher.IncludeSubdirectories = Settings.IncludeSubdirectories; + + _fileSystemWatcher.Created += FileWatcher_Created; + _fileSystemWatcher.Changed += FileWatcher_Changed; + _fileSystemWatcher.Renamed += FileWatcher_Renamed; + _fileSystemWatcher.Deleted += FileWatcher_Deleted; + + _fileSystemWatcher.EnableRaisingEvents = true; + DebugHelper.WriteLine($"Started monitoring directory: {folderPath} with filter: {_fileSystemWatcher.Filter}"); - fileWatcher = new FileSystemWatcher(folderPath); - if (!string.IsNullOrEmpty(Settings.Filter)) fileWatcher.Filter = Settings.Filter; - fileWatcher.IncludeSubdirectories = Settings.IncludeSubdirectories; - fileWatcher.Created += fileWatcher_Created; - fileWatcher.EnableRaisingEvents = true; + // If you still want to initialize PhysicalFileProvider for other (non-event) purposes: + _fileProvider = new PhysicalFileProvider(folderPath) + { + UsePollingFileWatcher = true, + UseActivePolling = true + }; + // Note: _fileProvider won't directly trigger the FileWatcherTrigger event. + // You'd need to manually check for changes using IChangeToken if you wanted to use it for eventing. + } + catch (Exception ex) + { + DebugHelper.WriteException(ex, $"Error enabling file watcher for {folderPath}"); } } - protected void OnFileWatcherTrigger(string? path) + /// + /// Invokes the FileWatcherTrigger event on the synchronization context. + /// + /// The path of the file that triggered the event. + private void OnFileWatcherTrigger(string? path) { - FileWatcherTrigger?.Invoke(path); + _context.Post(state => FileWatcherTrigger?.Invoke((string?)state), path); } - private async void fileWatcher_Created(object sender, FileSystemEventArgs e) + /// + /// Handles the FileSystemWatcher.Created event. + /// + private async void FileWatcher_Created(object sender, FileSystemEventArgs e) { - CleanElapsedTimers(); + DebugHelper.WriteLine($"File created event: {e.FullPath}"); + await HandleFileEvent(e.FullPath); + } + + /// + /// Handles the FileSystemWatcher.Changed event. + /// + private async void FileWatcher_Changed(object sender, FileSystemEventArgs e) + { + DebugHelper.WriteLine($"File changed event: {e.FullPath}"); + await HandleFileEvent(e.FullPath); + } - string? path = e.FullPath; + /// + /// Handles the FileSystemWatcher.Renamed event. + /// + private async void FileWatcher_Renamed(object sender, RenamedEventArgs e) + { + DebugHelper.WriteLine($"File renamed event: Old path: {e.OldFullPath}, New path: {e.FullPath}"); + // For renamed, we typically care about the new path + await HandleFileEvent(e.FullPath); + } - foreach (WatchFolderDuplicateEventTimer timer in timers) + /// + /// Handles the FileSystemWatcher.Deleted event. + /// + private void FileWatcher_Deleted(object sender, FileSystemEventArgs e) + { + DebugHelper.WriteLine($"File deleted event: {e.FullPath}"); + // No need to wait for file unlock/size for deleted files, just log or trigger if needed. + // For deletion, you might have a separate event or just log. + // If you need to trigger something for deleted files, consider a separate event or flag in FileWatcherTrigger. + } + + + /// + /// Common handler for file system events, including debounce and file locking checks. + /// + /// The full path of the file. + private async Task HandleFileEvent(string path) + { + CleanElapsedTimers(); + + // Skip directories for file processing + if (Directory.Exists(path)) { - if (timer.IsDuplicateEvent(path)) - { - return; - } + DebugHelper.WriteLine($"Skipping directory event for: {path}"); + return; } - timers.Add(new WatchFolderDuplicateEventTimer(path)); + // Debounce duplicate events + if (_timers.Any(timer => timer.IsDuplicateEvent(path))) + { + DebugHelper.WriteLine($"Skipping duplicate event for: {path}"); + return; + } + _timers.Add(new WatchFolderDuplicateEventTimer(path)); - int successCount = 0; + var successCount = 0; long previousSize = -1; - await Helpers.WaitWhileAsync(() => - { - if (!FileHelpers.IsFileLocked(path)) + // Wait until the file is no longer locked and its size stabilizes + await Helpers.WaitWhileAsync( + check: () => { - long currentSize = FileHelpers.GetFileSize(path); - - if (currentSize > 0 && currentSize == previousSize) + if (!File.Exists(path)) { - successCount++; + DebugHelper.WriteLine($"File {path} no longer exists during processing."); + return false; } - previousSize = currentSize; - return successCount < 4; - } + if (!FileHelpers.IsFileLocked(path)) + { + var currentSize = FileHelpers.GetFileSize(path); - previousSize = -1; - return true; - }, 250, 5000, () => - { - context.Post(state => OnFileWatcherTrigger(path), null); - }, 1000); + if (currentSize > 0 && currentSize == previousSize) + { + successCount++; + } + else + { + successCount = 0; + } + + previousSize = currentSize; + return successCount < 4; // Wait for 4 consecutive stable size readings + } + + previousSize = -1; // Reset previous size if file is locked + return true; + }, + interval: 250, + timeout: 5000, + waitStart: 0, + onSuccess: () => + { + OnFileWatcherTrigger(path); + }); } - protected void CleanElapsedTimers() + /// + /// Cleans up elapsed duplicate event timers. + /// + private void CleanElapsedTimers() { - for (int i = 0; i < timers.Count; i++) - { - if (timers[i].IsElapsed) - { - timers.Remove(timers[i]); - } - } + _timers.RemoveAll(timer => timer.IsElapsed); } + /// + /// Disposes the FileSystemWatcher. + /// public void Dispose() { - if (fileWatcher != null) + if (_fileSystemWatcher != null) { - fileWatcher.Dispose(); + _fileSystemWatcher.EnableRaisingEvents = false; + _fileSystemWatcher.Created -= FileWatcher_Created; + _fileSystemWatcher.Changed -= FileWatcher_Changed; + _fileSystemWatcher.Renamed -= FileWatcher_Renamed; + _fileSystemWatcher.Deleted -= FileWatcher_Deleted; + _fileSystemWatcher.Dispose(); + _fileSystemWatcher = null; + DebugHelper.WriteLine("FileSystemWatcher disposed."); } + _fileProvider?.Dispose(); + _fileProvider = null; } } public class WatchFolderDuplicateEventTimer { - private const int expireTime = 1000; + private const int ExpireTimeMs = 1000; // Timer expires after 1 second - private Stopwatch timer; - private string? path; + private Stopwatch _timer; + private string? _path; + /// + /// Indicates if the timer has elapsed. + /// public bool IsElapsed { get { - return timer.ElapsedMilliseconds >= expireTime; + return _timer.ElapsedMilliseconds >= ExpireTimeMs; } } + /// + /// Initializes a new instance of the WatchFolderDuplicateEventTimer. + /// + /// The path of the file. public WatchFolderDuplicateEventTimer(string? path) { - timer = Stopwatch.StartNew(); - this.path = path; + _timer = Stopwatch.StartNew(); + _path = path; } + /// + /// Checks if the given path is a duplicate event and restarts the timer if it is. + /// + /// The path to check. + /// True if it's a duplicate event within the expiration time, otherwise false. public bool IsDuplicateEvent(string? path) { - bool result = path == this.path && !IsElapsed; + bool result = path == _path && !IsElapsed; if (result) { - timer = Stopwatch.StartNew(); + _timer.Restart(); // Restart the timer for the duplicate event } return result; } } - diff --git a/SnapX.Core/Watch/WatchFolderManager.cs b/SnapX.Core/Watch/WatchFolderManager.cs index b45a2ed91..2bd41bf56 100644 --- a/SnapX.Core/Watch/WatchFolderManager.cs +++ b/SnapX.Core/Watch/WatchFolderManager.cs @@ -10,7 +10,7 @@ namespace SnapX.Core.Watch; public class WatchFolderManager : IDisposable { - public List WatchFolders { get; private set; } + public List? WatchFolders { get; private set; } public void UpdateWatchFolders() { @@ -26,16 +26,16 @@ public void UpdateWatchFolders() AddWatchFolder(defaultWatchFolderSetting, SnapX.DefaultTaskSettings); } - foreach (HotkeySettings hotkeySetting in SnapX.HotkeysConfig.Hotkeys) + foreach (var hotkeySetting in SnapX.HotkeysConfig.Hotkeys) { - foreach (WatchFolderSettings watchFolderSetting in hotkeySetting.TaskSettings.WatchFolderList) + foreach (var watchFolderSetting in hotkeySetting.TaskSettings.WatchFolderList) { AddWatchFolder(watchFolderSetting, hotkeySetting.TaskSettings); } } } - private WatchFolder FindWatchFolder(WatchFolderSettings watchFolderSetting) + private WatchFolder? FindWatchFolder(WatchFolderSettings watchFolderSetting) { return WatchFolders.FirstOrDefault(watchFolder => watchFolder.Settings == watchFolderSetting); } @@ -54,19 +54,19 @@ public void AddWatchFolder(WatchFolderSettings watchFolderSetting, TaskSettings? taskSettings.WatchFolderList.Add(watchFolderSetting); } - WatchFolder watchFolder = new WatchFolder(); + var watchFolder = new WatchFolder(); watchFolder.Settings = watchFolderSetting; watchFolder.TaskSettings = taskSettings; watchFolder.FileWatcherTrigger += origPath => { var taskSettingsCopy = TaskSettings.GetSafeTaskSettings(taskSettings); - string? destPath = origPath; + var destPath = origPath; if (watchFolderSetting.MoveFilesToScreenshotsFolder) { - string? screenshotsFolder = TaskHelpers.GetScreenshotsFolder(taskSettingsCopy); - string fileName = Path.GetFileName(origPath); + var screenshotsFolder = TaskHelpers.GetScreenshotsFolder(taskSettingsCopy); + var fileName = Path.GetFileName(origPath); destPath = Path.Combine(screenshotsFolder, fileName); FileHelpers.CreateDirectoryFromFilePath(destPath); File.Move(origPath, destPath); @@ -86,43 +86,32 @@ public void AddWatchFolder(WatchFolderSettings watchFolderSetting, TaskSettings? public void RemoveWatchFolder(WatchFolderSettings watchFolderSetting) { - using (WatchFolder watchFolder = FindWatchFolder(watchFolderSetting)) - { - if (watchFolder != null) - { - watchFolder.TaskSettings.WatchFolderList.Remove(watchFolderSetting); - WatchFolders.Remove(watchFolder); - } - } + using var watchFolder = FindWatchFolder(watchFolderSetting); + if (watchFolder == null) return; + watchFolder.TaskSettings?.WatchFolderList.Remove(watchFolderSetting); + WatchFolders?.Remove(watchFolder); } public void UpdateWatchFolderState(WatchFolderSettings watchFolderSetting) { - WatchFolder watchFolder = FindWatchFolder(watchFolderSetting); - if (watchFolder != null) + var watchFolder = FindWatchFolder(watchFolderSetting); + if (watchFolder == null) return; + if (watchFolder.TaskSettings?.WatchFolderEnabled ?? false) { - if (watchFolder.TaskSettings.WatchFolderEnabled) - { - watchFolder.Enable(); - } - else - { - watchFolder.Dispose(); - } + watchFolder.Enable(); + } + else + { + watchFolder.Dispose(); } } public void UnregisterAllWatchFolders() { - if (WatchFolders != null) + if (WatchFolders == null) return; + foreach (var watchFolder in WatchFolders.OfType()) { - foreach (WatchFolder watchFolder in WatchFolders) - { - if (watchFolder != null) - { - watchFolder.Dispose(); - } - } + watchFolder.Dispose(); } } From f35e4b7e557839970fdcf9ce4dcdbd08c8e23dca Mon Sep 17 00:00:00 2001 From: Brycen G Date: Sun, 20 Jul 2025 11:03:52 -0400 Subject: [PATCH 21/31] build: use MimeTypeCore instead of MimeTypes dependency --- SnapX.Core/SnapX.Core.csproj | 6 ++---- SnapX.Core/Upload/BaseUploaders/Uploader.cs | 3 ++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/SnapX.Core/SnapX.Core.csproj b/SnapX.Core/SnapX.Core.csproj index bccb06c67..831fdfcbf 100644 --- a/SnapX.Core/SnapX.Core.csproj +++ b/SnapX.Core/SnapX.Core.csproj @@ -24,10 +24,7 @@ $(DefineConstants);DISABLE_UPLOADS - + $(DefineConstants);DISABLE_OCR @@ -48,6 +45,7 @@ + diff --git a/SnapX.Core/Upload/BaseUploaders/Uploader.cs b/SnapX.Core/Upload/BaseUploaders/Uploader.cs index f136177cf..3035fc010 100644 --- a/SnapX.Core/Upload/BaseUploaders/Uploader.cs +++ b/SnapX.Core/Upload/BaseUploaders/Uploader.cs @@ -4,6 +4,7 @@ using System.Collections.Specialized; using System.Net; using System.Text; +using MimeTypeCore; using SnapX.Core.Upload.OAuth; using SnapX.Core.Upload.Utils; using SnapX.Core.Utils; @@ -255,7 +256,7 @@ protected UploadResult SendRequestFileRange(string? url, Stream data, string? fi } contentLength = Math.Min(contentLength, data.Length - contentPosition); - string contentType = MimeTypes.GetMimeType(fileName); + var contentType = MimeTypeMap.GetMimeType(fileName); if (headers == null) { From 03980effc07ecab93d2bf6861285a2a0d9a84627 Mon Sep 17 00:00:00 2001 From: Brycen G Date: Sun, 20 Jul 2025 12:32:52 -0400 Subject: [PATCH 22/31] chore: use WaylandSharp instead of WaylandSharper --- SnapX.Core/Utils/Native/LinuxAPI.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SnapX.Core/Utils/Native/LinuxAPI.cs b/SnapX.Core/Utils/Native/LinuxAPI.cs index a6e211cfd..6539fb8b2 100644 --- a/SnapX.Core/Utils/Native/LinuxAPI.cs +++ b/SnapX.Core/Utils/Native/LinuxAPI.cs @@ -5,7 +5,7 @@ using SixLabors.ImageSharp.PixelFormats; using SnapX.Core.Interfaces; using SnapX.Core.Media; -using WaylandSharper; +using WaylandSharp; namespace SnapX.Core.Utils.Native; From 4f0a1ecfba0950e0cbc403b48813d10e6bb615f4 Mon Sep 17 00:00:00 2001 From: Brycen G Date: Sun, 20 Jul 2025 17:51:21 -0400 Subject: [PATCH 23/31] chore: make sure ALL classes use MimeTypeCore --- SnapX.Avalonia/ViewModels/HomePageViewModel.cs | 10 +++++----- SnapX.Avalonia/Views/HomePageView.axaml.cs | 1 - SnapX.Core/Upload/File/AmazonS3.cs | 3 ++- SnapX.Core/Upload/File/AzureStorage.cs | 3 ++- SnapX.Core/Upload/File/BackblazeB2.cs | 3 ++- SnapX.Core/Upload/File/CustomFileUploader.cs | 3 ++- SnapX.Core/Upload/File/OwnCloud.cs | 3 ++- SnapX.Core/Upload/File/Plik.cs | 3 ++- SnapX.Core/Upload/Img/CustomImageUploader.cs | 3 ++- SnapX.Core/Upload/Text/CustomTextUploader.cs | 3 ++- SnapX.Core/Upload/Utils/RequestHelpers.cs | 5 +++-- SnapX.Core/Watch/WatchFolderManager.cs | 3 +-- 12 files changed, 25 insertions(+), 18 deletions(-) diff --git a/SnapX.Avalonia/ViewModels/HomePageViewModel.cs b/SnapX.Avalonia/ViewModels/HomePageViewModel.cs index 17160db7d..a09d33d95 100644 --- a/SnapX.Avalonia/ViewModels/HomePageViewModel.cs +++ b/SnapX.Avalonia/ViewModels/HomePageViewModel.cs @@ -203,12 +203,12 @@ public async Task RefreshTasks() var historyItems = await TaskManager.History.GetHistoryItemsAsync().ConfigureAwait(false); - var tasks = historyItems.Select(task => new ListTaskTemplate(typeofVM, task)); + var tasks = historyItems.Select(task => new ListTaskTemplate(typeofVM, task)); - var newDesiredTasks = tasks - .OrderByDescending(item => item.task.Id) - .ToList(); - await Task.Yield(); + var newDesiredTasks = tasks + .OrderByDescending(item => item.task.Id) + .ToList(); + await Task.Yield(); await Dispatcher.UIThread.InvokeAsync(() => { if (newDesiredTasks.Count > 50_000) diff --git a/SnapX.Avalonia/Views/HomePageView.axaml.cs b/SnapX.Avalonia/Views/HomePageView.axaml.cs index b830f717b..8ee4030a4 100644 --- a/SnapX.Avalonia/Views/HomePageView.axaml.cs +++ b/SnapX.Avalonia/Views/HomePageView.axaml.cs @@ -2,7 +2,6 @@ using Avalonia.Controls; using Avalonia.Interactivity; using FluentAvalonia.UI.Controls; -using SnapX.Avalonia.Services; using SnapX.Avalonia.ViewModels; using SnapX.CommonUI.Models; using SnapX.Core; diff --git a/SnapX.Core/Upload/File/AmazonS3.cs b/SnapX.Core/Upload/File/AmazonS3.cs index f5fe5f91d..2cf82941b 100644 --- a/SnapX.Core/Upload/File/AmazonS3.cs +++ b/SnapX.Core/Upload/File/AmazonS3.cs @@ -4,6 +4,7 @@ using System.Collections.Specialized; using System.ComponentModel; using System.Globalization; +using MimeTypeCore; using SnapX.Core.Upload.BaseServices; using SnapX.Core.Upload.BaseUploaders; using SnapX.Core.Upload.Custom; @@ -108,7 +109,7 @@ public override UploadResult Upload(Stream stream, string? fileName) var scope = URLHelpers.CombineURL(credentialDate, region, "s3", "aws4_request"); var credential = URLHelpers.CombineURL(Settings.AccessKeyID, scope); var timeStamp = DateTime.UtcNow.ToString("yyyyMMddTHHmmssZ", CultureInfo.InvariantCulture); - var contentType = MimeTypes.GetMimeType(fileName); + var contentType = MimeTypeMap.GetMimeType(fileName); string hashedPayload; if (Settings.SignedPayload) diff --git a/SnapX.Core/Upload/File/AzureStorage.cs b/SnapX.Core/Upload/File/AzureStorage.cs index 62141f9ea..d3f024817 100644 --- a/SnapX.Core/Upload/File/AzureStorage.cs +++ b/SnapX.Core/Upload/File/AzureStorage.cs @@ -5,6 +5,7 @@ using System.Globalization; using System.Security.Cryptography; using System.Text; +using MimeTypeCore; using SnapX.Core.Upload.BaseServices; using SnapX.Core.Upload.BaseUploaders; using SnapX.Core.Upload.Utils; @@ -73,7 +74,7 @@ public override UploadResult Upload(Stream stream, string? fileName) OnEarlyURLCopyRequested(resultURL); - var contentType = MimeTypes.GetMimeType(fileName); + var contentType = MimeTypeMap.GetMimeType(fileName); var requestHeaders = new NameValueCollection { { "x-ms-date", date }, diff --git a/SnapX.Core/Upload/File/BackblazeB2.cs b/SnapX.Core/Upload/File/BackblazeB2.cs index d69a5b955..a59e27873 100644 --- a/SnapX.Core/Upload/File/BackblazeB2.cs +++ b/SnapX.Core/Upload/File/BackblazeB2.cs @@ -9,6 +9,7 @@ using System.Security.Cryptography; using System.Text; using System.Text.Json; +using MimeTypeCore; using SnapX.Core.Upload.BaseServices; using SnapX.Core.Upload.BaseUploaders; using SnapX.Core.Upload.Utils; @@ -404,7 +405,7 @@ private B2UploadResult B2ApiUploadFile(B2UploadUrl b2UploadUrl, string? destinat ["X-Bz-Info-b2-content-disposition"] = URLHelpers.URLEncode(contentDisposition.ToString()), }; - string contentType = MimeTypes.GetMimeType(destinationPath); + string contentType = MimeTypeMap.GetMimeType(destinationPath); using var response = GetResponse(HttpMethod.Post, b2UploadUrl.uploadUrl, data: file, contentType: contentType, headers: headers, allowNon2xxResponses: true); diff --git a/SnapX.Core/Upload/File/CustomFileUploader.cs b/SnapX.Core/Upload/File/CustomFileUploader.cs index 1f255bb4f..ebf4dbf28 100644 --- a/SnapX.Core/Upload/File/CustomFileUploader.cs +++ b/SnapX.Core/Upload/File/CustomFileUploader.cs @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later +using MimeTypeCore; using SnapX.Core.Upload.BaseServices; using SnapX.Core.Upload.BaseUploaders; using SnapX.Core.Upload.Custom; @@ -63,7 +64,7 @@ public override UploadResult Upload(Stream stream, string? fileName) } else if (uploader.Body == CustomUploaderBody.Binary) { - result.Response = SendRequest(uploader.RequestMethod, uploader.GetRequestURL(input), stream, MimeTypes.GetMimeType(fileName), null, + result.Response = SendRequest(uploader.RequestMethod, uploader.GetRequestURL(input), stream, MimeTypeMap.GetMimeType(fileName), null, uploader.GetHeaders(input)); } else diff --git a/SnapX.Core/Upload/File/OwnCloud.cs b/SnapX.Core/Upload/File/OwnCloud.cs index 69fe5b56b..1b920e490 100644 --- a/SnapX.Core/Upload/File/OwnCloud.cs +++ b/SnapX.Core/Upload/File/OwnCloud.cs @@ -4,6 +4,7 @@ using System.Diagnostics.CodeAnalysis; using System.Text.Json; using System.Text.Json.Serialization; +using MimeTypeCore; using SnapX.Core.Upload.BaseServices; using SnapX.Core.Upload.BaseUploaders; using SnapX.Core.Upload.Utils; @@ -88,7 +89,7 @@ public override UploadResult Upload(Stream stream, string? fileName) var headers = RequestHelpers.CreateAuthenticationHeader(Username, Password); headers["OCS-APIREQUEST"] = "true"; - var response = SendRequest(HttpMethod.Put, url, stream, MimeTypes.GetMimeType(fileName), null, headers); + var response = SendRequest(HttpMethod.Put, url, stream, MimeTypeMap.GetMimeType(fileName), null, headers); var result = new UploadResult(response); diff --git a/SnapX.Core/Upload/File/Plik.cs b/SnapX.Core/Upload/File/Plik.cs index f80976e64..6e3533daf 100644 --- a/SnapX.Core/Upload/File/Plik.cs +++ b/SnapX.Core/Upload/File/Plik.cs @@ -5,6 +5,7 @@ using System.Diagnostics.CodeAnalysis; using System.Text.Json; using System.Text.Json.Serialization; +using MimeTypeCore; using SnapX.Core.Upload.BaseServices; using SnapX.Core.Upload.BaseUploaders; using SnapX.Core.Upload.Utils; @@ -53,7 +54,7 @@ public override UploadResult Upload(Stream stream, string? fileName) metaDataReq.Files = new UploadMetadataRequestFile0(); metaDataReq.Files.File0 = new UploadMetadataRequestFile(); metaDataReq.Files.File0.FileName = fileName; - metaDataReq.Files.File0.FileType = MimeTypes.GetMimeType(fileName); + metaDataReq.Files.File0.FileType = MimeTypeMap.GetMimeType(fileName); metaDataReq.Files.File0.FileSize = Convert.ToInt32(stream.Length); metaDataReq.Removable = Settings.Removable; metaDataReq.OneShot = Settings.OneShot; diff --git a/SnapX.Core/Upload/Img/CustomImageUploader.cs b/SnapX.Core/Upload/Img/CustomImageUploader.cs index b44fd60fa..052baa64b 100644 --- a/SnapX.Core/Upload/Img/CustomImageUploader.cs +++ b/SnapX.Core/Upload/Img/CustomImageUploader.cs @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later +using MimeTypeCore; using SnapX.Core.Upload.BaseServices; using SnapX.Core.Upload.BaseUploaders; using SnapX.Core.Upload.Custom; @@ -56,7 +57,7 @@ public override UploadResult Upload(Stream stream, string? fileName) } else if (uploader.Body == CustomUploaderBody.Binary) { - ur.Response = SendRequest(uploader.RequestMethod, uploader.GetRequestURL(input), stream, MimeTypes.GetMimeType(fileName), + ur.Response = SendRequest(uploader.RequestMethod, uploader.GetRequestURL(input), stream, MimeTypeMap.GetMimeType(fileName), null, uploader.GetHeaders(input)); } else diff --git a/SnapX.Core/Upload/Text/CustomTextUploader.cs b/SnapX.Core/Upload/Text/CustomTextUploader.cs index 9bca8f8a3..e3f3b39cd 100644 --- a/SnapX.Core/Upload/Text/CustomTextUploader.cs +++ b/SnapX.Core/Upload/Text/CustomTextUploader.cs @@ -2,6 +2,7 @@ using System.Text; +using MimeTypeCore; using SnapX.Core.Upload.BaseServices; using SnapX.Core.Upload.BaseUploaders; using SnapX.Core.Upload.Custom; @@ -122,7 +123,7 @@ public override UploadResult UploadText(string? text, string? fileName) uploader.RequestMethod, uploader.GetRequestURL(input), binaryStream, - MimeTypes.GetMimeType(fileName), + MimeTypeMap.GetMimeType(fileName), null, uploader.GetHeaders(input) ); diff --git a/SnapX.Core/Upload/Utils/RequestHelpers.cs b/SnapX.Core/Upload/Utils/RequestHelpers.cs index e223c9ef4..6e58caab0 100644 --- a/SnapX.Core/Upload/Utils/RequestHelpers.cs +++ b/SnapX.Core/Upload/Utils/RequestHelpers.cs @@ -4,6 +4,7 @@ using System.Collections.Specialized; using System.Net; using System.Text; +using MimeTypeCore; using SnapX.Core.Utils.Cryptographic; namespace SnapX.Core.Upload.Utils; @@ -138,14 +139,14 @@ public static byte[] MakeInputContent(string boundary, Dictionary Date: Fri, 25 Jul 2025 12:48:02 -0400 Subject: [PATCH 24/31] fix(Core): add optimized parameters for SQLite --- SnapX.Core/SnapX.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/SnapX.Core/SnapX.cs b/SnapX.Core/SnapX.cs index e16d002c4..28dc47a3d 100644 --- a/SnapX.Core/SnapX.cs +++ b/SnapX.Core/SnapX.cs @@ -391,6 +391,10 @@ private void Run() var connectionString = new SqliteConnectionStringBuilder { DataSource = dataSource, Mode = SqliteOpenMode.ReadWriteCreate, Cache = SqliteCacheMode.Shared, ForeignKeys = true, Pooling = true, }.ToString(); DbConnection = new SqliteConnection(connectionString); RunWithTimeout(() => DbConnection.OpenAsync(), $"Opening the database connection at {DBPath}"); + RunWithTimeout(() => DbConnection.ExecuteAsync("PRAGMA busy_timeout = 5000;"), "Setting busy timeout"); + RunWithTimeout(() => DbConnection.ExecuteAsync("PRAGMA temp_store = MEMORY;"), "Setting temp_store"); + RunWithTimeout(() => DbConnection.ExecuteAsync("PRAGMA mmap_size = 30000000000;"), "Setting mmap_size"); + RunWithTimeout(() => DbConnection.ExecuteAsync("PRAGMA cache_size = -64000;"), "Setting cache_size"); RunWithTimeout(() => DbConnection.ExecuteAsync("PRAGMA journal_mode=WAL;"), "Setting journal mode"); _ = Task.Run(() => { @@ -442,7 +446,9 @@ private void Run() IsDebugMode = false #endif }, logger); - var telemetry = new Telemetry(DbConnection, aptabaseClient); + var loggerService = serviceProvider.GetRequiredService(); + + var telemetry = new Telemetry(DbConnection, aptabaseClient, loggerService); SnapX.aptabaseClient = aptabaseClient; telemetry.TrackEvent("app_started", new Dictionary { From 446625578cb743086453fc0941801dd1075c8819 Mon Sep 17 00:00:00 2001 From: Brycen G Date: Fri, 25 Jul 2025 12:48:42 -0400 Subject: [PATCH 25/31] chore: remove debug statements from UI loop --- SnapX.Avalonia/ViewModels/HomePageViewModel.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/SnapX.Avalonia/ViewModels/HomePageViewModel.cs b/SnapX.Avalonia/ViewModels/HomePageViewModel.cs index a09d33d95..e9b41efe1 100644 --- a/SnapX.Avalonia/ViewModels/HomePageViewModel.cs +++ b/SnapX.Avalonia/ViewModels/HomePageViewModel.cs @@ -226,7 +226,6 @@ await Dispatcher.UIThread.InvokeAsync(() => { if (!newDesiredTaskIds.Contains(recentTasks[i].task.Id)) { - DebugHelper.WriteLine($"Removing {recentTasks[i].task.Id}"); recentTasks.RemoveAt(i); } } @@ -240,7 +239,6 @@ await Dispatcher.UIThread.InvokeAsync(() => continue; } var index = recentTasks.IndexOf(existingItem); - DebugHelper.WriteLine($"Replacing {index}"); if (index == -1) continue; recentTasks.RemoveAt(index); From c80184b482f297245e9b2b171a6dd7a49496ce3d Mon Sep 17 00:00:00 2001 From: Brycen G Date: Fri, 25 Jul 2025 12:49:05 -0400 Subject: [PATCH 26/31] build(Core): make sure WaylandSharper is a explicit source gen dependency --- SnapX.Core/SnapX.Core.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SnapX.Core/SnapX.Core.csproj b/SnapX.Core/SnapX.Core.csproj index ac3d0b694..1121cad49 100644 --- a/SnapX.Core/SnapX.Core.csproj +++ b/SnapX.Core/SnapX.Core.csproj @@ -73,7 +73,7 @@ hiding them behind a compiler conditional makes debugging more difficult. --> - + From 1dcbf0dedc9154e52ba1b81a2c4e82c2026ddf60 Mon Sep 17 00:00:00 2001 From: Brycen G Date: Fri, 25 Jul 2025 15:59:02 -0400 Subject: [PATCH 27/31] perf(Avalonia): reduce UI thread blocking in RefreshTasks for large task updates - Now scales to a large amount of items without flickering. - Resolved missing symbol 'FindIndex' by introducing an extension method for AvaloniaList. - Optimized recentTasks update logic: - Replaced full list clear/add with incremental mutation using RemoveAt and Insert. - Used reverse iteration for safe in-place removal of old items (`toRemove`). - Applied targeted replacement for items in `toUpdate` via FindIndex. - Prepended new items (`toAdd`) to maintain order and avoid unnecessary sorting. - Wrapped UI update logic in Dispatcher.UIThread.InvokeAsync to ensure thread safety. - Appended GetTask().ConfigureAwait(false) to ensure the continuation is offloaded from the UI thread, improving responsiveness and avoiding unnecessary context switches. These changes improve UI smoothness, avoid layout flicker, prevent unnecessary reallocation, and ensure the async flow is context-aware and lightweight. --- .../Extensions/AvaloniaListExtensions.cs | 20 +++++ .../ViewModels/HomePageViewModel.cs | 76 ++++++++++--------- 2 files changed, 62 insertions(+), 34 deletions(-) create mode 100644 SnapX.Avalonia/Extensions/AvaloniaListExtensions.cs diff --git a/SnapX.Avalonia/Extensions/AvaloniaListExtensions.cs b/SnapX.Avalonia/Extensions/AvaloniaListExtensions.cs new file mode 100644 index 000000000..8ae9ff1b7 --- /dev/null +++ b/SnapX.Avalonia/Extensions/AvaloniaListExtensions.cs @@ -0,0 +1,20 @@ +using Avalonia.Collections; + +namespace SnapX.Avalonia.Extensions; + +public static class AvaloniaListExtensions +{ + public static int FindIndex(this AvaloniaList list, Predicate match) + { + if (match == null) + throw new ArgumentNullException(nameof(match)); + + for (int i = 0; i < list.Count; i++) + { + if (match(list[i])) + return i; + } + + return -1; + } +} diff --git a/SnapX.Avalonia/ViewModels/HomePageViewModel.cs b/SnapX.Avalonia/ViewModels/HomePageViewModel.cs index e9b41efe1..149d596c4 100644 --- a/SnapX.Avalonia/ViewModels/HomePageViewModel.cs +++ b/SnapX.Avalonia/ViewModels/HomePageViewModel.cs @@ -4,6 +4,7 @@ using Avalonia.Input; using Avalonia.Threading; using CommunityToolkit.Mvvm.Input; +using SnapX.Avalonia.Extensions; using SnapX.Avalonia.Views; using SnapX.CommonUI.Models; using SnapX.CommonUI.ViewModels; @@ -203,52 +204,59 @@ public async Task RefreshTasks() var historyItems = await TaskManager.History.GetHistoryItemsAsync().ConfigureAwait(false); - var tasks = historyItems.Select(task => new ListTaskTemplate(typeofVM, task)); - - var newDesiredTasks = tasks + var tasks = historyItems + .Select(task => new ListTaskTemplate(typeofVM, task)) .OrderByDescending(item => item.task.Id) .ToList(); - await Task.Yield(); - await Dispatcher.UIThread.InvokeAsync(() => + + List toAdd = []; + List toUpdate = []; + List toRemove; + { - if (newDesiredTasks.Count > 50_000) + var currentTasksById = recentTasks.ToDictionary(t => t.task.Id); + var newTaskIds = tasks.Select(t => t.task.Id).ToHashSet(); + + toRemove = recentTasks + .Where(t => !newTaskIds.Contains(t.task.Id)) + .Select(t => t.task.Id) + .ToList(); + + foreach (var newItem in tasks) { - recentTasks.ResetBehavior = ResetBehavior.Remove; - recentTasks.Clear(); - recentTasks.AddRange(newDesiredTasks); - return; + if (currentTasksById.TryGetValue(newItem.task.Id, out var existing)) + { + if (!existing.Equals(newItem)) + toUpdate.Add(newItem); + } + else + { + toAdd.Add(newItem); + } } - var currentTasksById = recentTasks.ToDictionary(template => template.task.Id); - - var newDesiredTaskIds = newDesiredTasks.Select(template => template.task.Id).ToHashSet(); + } + // Warning: Computations on the UIThread are precious. + await Dispatcher.UIThread.InvokeAsync(() => + { for (var i = recentTasks.Count - 1; i >= 0; i--) { - if (!newDesiredTaskIds.Contains(recentTasks[i].task.Id)) - { + if (toRemove.Contains(recentTasks[i].task.Id)) recentTasks.RemoveAt(i); - } } - foreach (var newItem in newDesiredTasks) + foreach (var item in toUpdate) { - if (currentTasksById.TryGetValue(newItem.task.Id, out var existingItem)) - { - if (existingItem.Equals(newItem)) - { - continue; - } - var index = recentTasks.IndexOf(existingItem); - - if (index == -1) continue; - recentTasks.RemoveAt(index); - recentTasks.Insert(index, newItem); - } - else - { - recentTasks.Insert(0, newItem); - } + var index = recentTasks.FindIndex(t => t.task.Id == item.task.Id); + if (index == -1) continue; + recentTasks.RemoveAt(index); + recentTasks.Insert(index, item); + } + + foreach (var item in toAdd) + { + recentTasks.Insert(0, item); } - }); + }).GetTask().ConfigureAwait(false); } } From 0d9d0293a425f6c5b23ce2c46fab872f603eeb82 Mon Sep 17 00:00:00 2001 From: Brycen G Date: Wed, 30 Jul 2025 07:51:26 -0400 Subject: [PATCH 28/31] style: run dotnet format --- SnapX.Avalonia/ViewModels/HomePageViewModel.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/SnapX.Avalonia/ViewModels/HomePageViewModel.cs b/SnapX.Avalonia/ViewModels/HomePageViewModel.cs index 149d596c4..6081980c8 100644 --- a/SnapX.Avalonia/ViewModels/HomePageViewModel.cs +++ b/SnapX.Avalonia/ViewModels/HomePageViewModel.cs @@ -27,13 +27,14 @@ public void InvalidateCache() } // ShowContextMenuCommand = new RelayCommand(ShowContextMenu); - public async Task Initialize() + public Task Initialize() { TaskManager.InitHistoryManager(); _refreshTimer.Elapsed += OnRefreshTimerElapsed; _refreshTimer.AutoReset = true; _refreshTimer.Start(); - RefreshTasks(); + _ = RefreshTasks(); + return Task.CompletedTask; } public void StopTimer() => _refreshTimer.Stop(); public void StartTimer() => _refreshTimer.Start(); @@ -78,13 +79,14 @@ private async void OnRefreshTimerElapsed(object sender, ElapsedEventArgs e) [RelayCommand] public void ContextMenuSelection(object Sender) { - SelectedTasks.Add(Sender as ListTaskTemplate); + if (Sender is not ListTaskTemplate Template) return; + SelectedTasks.Add(Template); } [RelayCommand] public void DeleteHistoryItemLocally(object Sender) { - var ltt = Sender as ListTaskTemplate; + if (Sender is not ListTaskTemplate ltt) return; var task = ltt.task; if (string.IsNullOrWhiteSpace(task.FilePath)) { @@ -145,7 +147,7 @@ private void OnPointerPress(object sender, PointerPressedEventArgs e) if (e.GetCurrentPoint(button).Properties.IsRightButtonPressed) { - // Right-click: Show context menu on the toggle button itself + // Right-click: Show a context menu on the toggle button itself vm.ContextMenuSelectionCommand.Execute(button); } else if (e.GetCurrentPoint(button).Properties.IsLeftButtonPressed) From 45a5786d9d7dbc183e2319f41cd24c6830d870d7 Mon Sep 17 00:00:00 2001 From: Brycen G Date: Sun, 3 Aug 2025 10:36:24 -0400 Subject: [PATCH 29/31] fix(Core): use json string enum converters for settings --- SnapX.Core/SettingManager.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/SnapX.Core/SettingManager.cs b/SnapX.Core/SettingManager.cs index d860657ee..5bf0c3af2 100644 --- a/SnapX.Core/SettingManager.cs +++ b/SnapX.Core/SettingManager.cs @@ -215,7 +215,8 @@ public static void SaveApplicationConfig() { WriteIndented = true, TypeInfoResolver = SettingsContext.Default, - DefaultIgnoreCondition = JsonIgnoreCondition.Never + DefaultIgnoreCondition = JsonIgnoreCondition.Never, + Converters = { new JsonStringEnumConverter() } }); File.WriteAllText(configFilePath, json); } @@ -236,7 +237,9 @@ public static void SaveUploadConfig() var json = JsonSerializer.Serialize(UploadersConfig, new JsonSerializerOptions { WriteIndented = true, - TypeInfoResolver = SettingsContext.Default + TypeInfoResolver = SettingsContext.Default, + Converters = { new JsonStringEnumConverter() } + }); File.WriteAllText(configFilePath, json); } @@ -257,7 +260,8 @@ public static void SaveHotkeysConfig() var json = JsonSerializer.Serialize(HotkeysConfig, new JsonSerializerOptions { WriteIndented = true, - TypeInfoResolver = SettingsContext.Default + TypeInfoResolver = SettingsContext.Default, + Converters = { new JsonStringEnumConverter() } }); File.WriteAllText(configFilePath, json); } From 6366c1ade8c557b13428936aad013803f6f02810 Mon Sep 17 00:00:00 2001 From: Brycen G Date: Tue, 12 Aug 2025 20:03:02 -0400 Subject: [PATCH 30/31] fix(Avalonia): use HardwareAccelerated setting --- SnapX.Avalonia/Program.cs | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/SnapX.Avalonia/Program.cs b/SnapX.Avalonia/Program.cs index de20b7bb4..53daf65cd 100644 --- a/SnapX.Avalonia/Program.cs +++ b/SnapX.Avalonia/Program.cs @@ -12,7 +12,7 @@ BuildAvaloniaApp() .StartWithClassicDesktopLifetime(args); -static AppBuilder BuildAvaloniaApp() +AppBuilder BuildAvaloniaApp() { var builder = AppBuilder.Configure() .WithInterFont(); @@ -23,8 +23,8 @@ static AppBuilder BuildAvaloniaApp() builder = builder.With(new FontManagerOptions { DefaultFamilyName = "fonts:Inter#Inter", - FontFallbacks = new List - { + FontFallbacks = + [ new() { FontFamily = "fonts:Inter#Inter" @@ -45,12 +45,13 @@ static AppBuilder BuildAvaloniaApp() { FontFamily = "Adwaita Sans" } - } + ] }); } builder = builder.LogToTrace(); + var useGPU = snapx.GetConfiguration().HardwareAccelerated; var x11Options = new X11PlatformOptions { // Fixes poor performance on my NVIDIA RTX 3060 Laptop GPU using Region Selector on Fedora KDE Wayland @@ -58,6 +59,21 @@ static AppBuilder BuildAvaloniaApp() UseRetainedFramebuffer = true, OverlayPopups = true }; + if (!useGPU) x11Options.RenderingMode = [X11RenderingMode.Software]; + + var macOSOptions = new AvaloniaNativePlatformOptions + { + RenderingMode = [AvaloniaNativeRenderingMode.Metal, AvaloniaNativeRenderingMode.OpenGl, AvaloniaNativeRenderingMode.Software], + OverlayPopups = true + }; + if (!useGPU) macOSOptions.RenderingMode = [AvaloniaNativeRenderingMode.Software]; + + var win32Options = new Win32PlatformOptions + { + RenderingMode = [Win32RenderingMode.Vulkan, Win32RenderingMode.AngleEgl, Win32RenderingMode.Wgl, Win32RenderingMode.Software], + OverlayPopups = true + }; + if (!useGPU) win32Options.RenderingMode = [Win32RenderingMode.Software]; if (OperatingSystem.IsFreeBSD()) { @@ -72,8 +88,8 @@ static AppBuilder BuildAvaloniaApp() .UsePlatformDetect() .UseManagedSystemDialogs() .With(x11Options) - .With(new AvaloniaNativePlatformOptions { OverlayPopups = true }) - .With(new Win32PlatformOptions { OverlayPopups = true }); + .With(macOSOptions) + .With(win32Options); } return builder; From 461d4c67b16853c6db63721371b706afb2dc4dbe Mon Sep 17 00:00:00 2001 From: Brycen G Date: Wed, 13 Aug 2025 20:53:37 -0400 Subject: [PATCH 31/31] chore(Avalonia): use default Avalonia rendering on Windows --- SnapX.Avalonia/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SnapX.Avalonia/Program.cs b/SnapX.Avalonia/Program.cs index 53daf65cd..4ca698d11 100644 --- a/SnapX.Avalonia/Program.cs +++ b/SnapX.Avalonia/Program.cs @@ -70,7 +70,7 @@ AppBuilder BuildAvaloniaApp() var win32Options = new Win32PlatformOptions { - RenderingMode = [Win32RenderingMode.Vulkan, Win32RenderingMode.AngleEgl, Win32RenderingMode.Wgl, Win32RenderingMode.Software], + // RenderingMode = [Win32RenderingMode.Vulkan, Win32RenderingMode.AngleEgl, Win32RenderingMode.Wgl, Win32RenderingMode.Software], OverlayPopups = true }; if (!useGPU) win32Options.RenderingMode = [Win32RenderingMode.Software];