├── .github
├── FUNDING.yml
├── release-drafter.yml
└── workflows
│ └── release-drafter.yml
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── imgs
├── add_page_dark.png
├── banner.png
├── code_view_page.png
├── cutcode.gif
├── fav_page.png
├── main_page.png
├── main_page_light.png
├── main_page_search.png
├── setting_dark.png
└── setting_light.png
└── src
├── .gitattributes
├── .gitignore
├── CutCode.CrossPlatform
├── .gitignore
├── App.axaml
├── App.axaml.cs
├── Assets
│ ├── Fonts
│ │ ├── Inconsolata-Regular.ttf
│ │ ├── Poppins-Regular.ttf
│ │ └── Poppins-SemiBold.ttf
│ ├── Images
│ │ ├── Developers
│ │ │ ├── abdesol.png
│ │ │ └── piero.png
│ │ ├── logo.ico
│ │ └── logo.png
│ └── avalonia-logo.ico
├── BootStrappers
│ ├── EntryBootstrapper.cs
│ ├── NavigationBootstrapper.cs
│ └── ServicesBootstrapper.cs
├── Controls
│ ├── AnimatedListBox.cs
│ ├── AnimatedListBoxItem.cs
│ ├── CustomComboBox.axaml
│ ├── CustomComboBox.axaml.cs
│ ├── CustomSearchBar.axaml
│ ├── CustomSearchBar.axaml.cs
│ ├── NavigationItem.axaml
│ ├── NavigationItem.axaml.cs
│ ├── WindowButtons.axaml
│ └── WindowButtons.axaml.cs
├── Converters
│ ├── BitmapAssetValueConverter.cs
│ ├── StringToFontFamily.cs
│ └── StringToGeometryConverter.cs
├── CutCode.CrossPlatform.csproj
├── FodyWeavers.xml
├── Helpers
│ ├── ButtonExts.cs
│ ├── Extensions.cs
│ ├── GlobalEvents.cs
│ ├── IconPaths.cs
│ ├── Languages.cs
│ ├── SystemColorsConfig.cs
│ └── UpdateChecker.cs
├── Models
│ ├── CodeModel.cs
│ ├── CodesTable.cs
│ ├── NotificationModels.cs
│ ├── PrefModel.cs
│ ├── SideBarBtnModel.cs
│ ├── SyncBtnModel.cs
│ ├── TabItemModel.cs
│ └── ThemeButtonModel.cs
├── Program.cs
├── Properties
│ └── launchSettings.json
├── Services
│ ├── DatabaseService.cs
│ ├── NotificationService.cs
│ ├── PageService.cs
│ └── ThemeService.cs
├── Styles
│ ├── AnimatedListBoxItem.axaml
│ ├── ButtonStyles.axaml
│ ├── ComboBox.axaml
│ ├── ScrollBarStyles.axaml
│ └── TextBoxStyles.axaml
├── ViewLocator.cs
├── ViewModels
│ ├── AddViewModel.cs
│ ├── CodeCardViewModel.cs
│ ├── CodeCellViewModel.cs
│ ├── CodeViewModel.cs
│ ├── FavoritesViewModel.cs
│ ├── HomeViewModel.cs
│ ├── MainWindowViewModel.cs
│ ├── NotificationViewModel.cs
│ ├── PageBaseViewModel.cs
│ ├── SettingsViewModel.cs
│ └── ViewModelBase.cs
├── Views
│ ├── AddView.axaml
│ ├── AddView.axaml.cs
│ ├── CodeCardView.axaml
│ ├── CodeCardView.axaml.cs
│ ├── CodeCellView.axaml
│ ├── CodeCellView.axaml.cs
│ ├── CodeView.axaml
│ ├── CodeView.axaml.cs
│ ├── FavoritesView.axaml
│ ├── FavoritesView.axaml.cs
│ ├── HomeView.axaml
│ ├── HomeView.axaml.cs
│ ├── MainWindow.axaml
│ ├── MainWindow.axaml.cs
│ ├── NotificationView.axaml
│ ├── NotificationView.axaml.cs
│ ├── SettingsView.axaml
│ └── SettingsView.axaml.cs
├── global.json
└── nuget.config
├── CutCode.sln
├── global.json
└── nuget.config
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | custom: "https://www.buymeacoffee.com/abdesol"
4 |
--------------------------------------------------------------------------------
/.github/release-drafter.yml:
--------------------------------------------------------------------------------
1 | name-template: 'v$RESOLVED_VERSION 🌈'
2 | tag-template: 'v$RESOLVED_VERSION'
3 | categories:
4 | - title: '🚀 Features'
5 | labels:
6 | - 'feature'
7 | - 'enhancement'
8 | - title: '🐛 Bug Fixes'
9 | labels:
10 | - 'fix'
11 | - 'bugfix'
12 | - 'bug'
13 | - title: '🧰 Maintenance'
14 | label: 'chore'
15 | change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
16 | change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks.
17 | version-resolver:
18 | major:
19 | labels:
20 | - 'major'
21 | minor:
22 | labels:
23 | - 'minor'
24 | patch:
25 | labels:
26 | - 'patch'
27 | default: patch
28 | template: |
29 | ## Changes
30 |
31 | $CHANGES
32 | autolabeler:
33 | - label: 'bug'
34 | title:
35 | - '/fix/i'
36 | - label: 'feature'
37 | title:
38 | - '/feature/i'
39 | - label: 'chore'
40 | title:
41 | - '/chore/i'
--------------------------------------------------------------------------------
/.github/workflows/release-drafter.yml:
--------------------------------------------------------------------------------
1 | name: Release Drafter
2 |
3 | on:
4 | push:
5 | # branches to consider in the event; optional, defaults to all
6 | branches:
7 | - master
8 | # pull_request event is required only for autolabeler
9 | pull_request:
10 | # Only following types are handled by the action, but one can default to all as well
11 | types: [ opened, reopened, synchronize ]
12 | # pull_request_target event is required for autolabeler to support PRs from forks
13 | # pull_request_target:
14 | # types: [opened, reopened, synchronize]
15 |
16 | jobs:
17 | update_release_draft:
18 | runs-on: ubuntu-latest
19 | steps:
20 | # (Optional) GitHub Enterprise requires GHE_HOST variable set
21 | #- name: Set GHE_HOST
22 | # run: |
23 | # echo "GHE_HOST=${GITHUB_SERVER_URL##https:\/\/}" >> $GITHUB_ENV
24 |
25 | # Drafts your next Release notes as Pull Requests are merged into "master"
26 | - uses: release-drafter/release-drafter@v5
27 | # (Optional) specify config name to use, relative to .github/. Default: release-drafter.yml
28 | # with:
29 | # config-name: my-config.yml
30 | # disable-autolabeler: true
31 | env:
32 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our
6 | community a harassment-free experience for everyone, regardless of age, body
7 | size, visible or invisible disability, ethnicity, sex characteristics, gender
8 | identity and expression, level of experience, education, socio-economic status,
9 | nationality, personal appearance, race, religion, or sexual identity
10 | and orientation.
11 |
12 | We pledge to act and interact in ways that contribute to an open, welcoming,
13 | diverse, inclusive, and healthy community.
14 |
15 | ## Our Standards
16 |
17 | Examples of behavior that contributes to a positive environment for our
18 | community include:
19 |
20 | * Demonstrating empathy and kindness toward other people
21 | * Being respectful of differing opinions, viewpoints, and experiences
22 | * Giving and gracefully accepting constructive feedback
23 | * Accepting responsibility and apologizing to those affected by our mistakes,
24 | and learning from the experience
25 | * Focusing on what is best not just for us as individuals, but for the
26 | overall community
27 |
28 | Examples of unacceptable behavior include:
29 |
30 | * The use of sexualized language or imagery, and sexual attention or
31 | advances of any kind
32 | * Trolling, insulting or derogatory comments, and personal or political attacks
33 | * Public or private harassment
34 | * Publishing others' private information, such as a physical or email
35 | address, without their explicit permission
36 | * Other conduct which could reasonably be considered inappropriate in a
37 | professional setting
38 |
39 | ## Enforcement Responsibilities
40 |
41 | Community leaders are responsible for clarifying and enforcing our standards of
42 | acceptable behavior and will take appropriate and fair corrective action in
43 | response to any behavior that they deem inappropriate, threatening, offensive,
44 | or harmful.
45 |
46 | Community leaders have the right and responsibility to remove, edit, or reject
47 | comments, commits, code, wiki edits, issues, and other contributions that are
48 | not aligned to this Code of Conduct, and will communicate reasons for moderation
49 | decisions when appropriate.
50 |
51 | ## Scope
52 |
53 | This Code of Conduct applies within all community spaces, and also applies when
54 | an individual is officially representing the community in public spaces.
55 | Examples of representing our community include using an official e-mail address,
56 | posting via an official social media account, or acting as an appointed
57 | representative at an online or offline event.
58 |
59 | ## Enforcement
60 |
61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 | reported to the community leaders responsible for enforcement at
63 | abdesoltak@gmail.com.
64 | All complaints will be reviewed and investigated promptly and fairly.
65 |
66 | All community leaders are obligated to respect the privacy and security of the
67 | reporter of any incident.
68 |
69 | ## Enforcement Guidelines
70 |
71 | Community leaders will follow these Community Impact Guidelines in determining
72 | the consequences for any action they deem in violation of this Code of Conduct:
73 |
74 | ### 1. Correction
75 |
76 | **Community Impact**: Use of inappropriate language or other behavior deemed
77 | unprofessional or unwelcome in the community.
78 |
79 | **Consequence**: A private, written warning from community leaders, providing
80 | clarity around the nature of the violation and an explanation of why the
81 | behavior was inappropriate. A public apology may be requested.
82 |
83 | ### 2. Warning
84 |
85 | **Community Impact**: A violation through a single incident or series
86 | of actions.
87 |
88 | **Consequence**: A warning with consequences for continued behavior. No
89 | interaction with the people involved, including unsolicited interaction with
90 | those enforcing the Code of Conduct, for a specified period of time. This
91 | includes avoiding interactions in community spaces as well as external channels
92 | like social media. Violating these terms may lead to a temporary or
93 | permanent ban.
94 |
95 | ### 3. Temporary Ban
96 |
97 | **Community Impact**: A serious violation of community standards, including
98 | sustained inappropriate behavior.
99 |
100 | **Consequence**: A temporary ban from any sort of interaction or public
101 | communication with the community for a specified period of time. No public or
102 | private interaction with the people involved, including unsolicited interaction
103 | with those enforcing the Code of Conduct, is allowed during this period.
104 | Violating these terms may lead to a permanent ban.
105 |
106 | ### 4. Permanent Ban
107 |
108 | **Community Impact**: Demonstrating a pattern of violation of community
109 | standards, including sustained inappropriate behavior, harassment of an
110 | individual, or aggression toward or disparagement of classes of individuals.
111 |
112 | **Consequence**: A permanent ban from any sort of public interaction within
113 | the community.
114 |
115 | ## Attribution
116 |
117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118 | version 2.0, available at
119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
120 |
121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct
122 | enforcement ladder](https://github.com/mozilla/diversity).
123 |
124 | [homepage]: https://www.contributor-covenant.org
125 |
126 | For answers to common questions about this code of conduct, see the FAQ at
127 | https://www.contributor-covenant.org/faq. Translations are available at
128 | https://www.contributor-covenant.org/translations.
129 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Abdella Solomon
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 |
4 | # CutCode
5 |
6 | As a developer, we often search on Google / StackOverFlow for doubts, issues related to our code and our projects, when programming / developing. As a result, we visit a lot of different posts, different websites to find the right solution to our problem, but time and (time) again, when we find a proper solution to your problem, we tend to forget where we found it or even the solution. Hence, we decided to create a tool that helps us save our answers as small snippets, so that we do not have remember it all the time and we can access our solutions anytime we want.
7 |
8 | CutCode is an open source tool made for developers to boost their productivity and save their time by helping them save essential code as snippets in safe place. These code snippets are stored in an orderly fashion and can be searched and accessed at anytime. It is a very helpful tool as the developers no longer need to remember their solutions and where they originally found them.
9 |
10 |
11 | # CutCode in Action 🎨
12 | 
13 |
14 |
15 | # Features ✨
16 |
17 | 1. **Dark and Light mode support. We recommend using dark mode for a better experience.**
18 | 2. **Your code snippets are saved safely in a database, in your system.**
19 | 3. **You can give your code snippets title, description, and also you can add them to your favourite snippets list.**
20 | 4. **You can add cells into your code so that you can manage your code snippets easily.**
21 | 5. **The code snippets are stored in orderly fashion, so you can search your snippets based on its name, programming language, and creation date.**
22 | 6. **CutCode has minimalistic UI design and it is user-friendly.**
23 | 7. **You can import and export your code from your system and save them as snippets.**
24 | 8. **CutCode is supported on both Windows and Linux.**
25 |
26 | # Coming Soon
27 | 1. **Syntax highlighting for all the programming languages supported by CutCode.**
28 | 2. **MacOS support.**
29 | 3. **Theme changing and plugins.**
30 | 4. **Automatic updater.**
31 | 5. **Animations everywhere**
32 |
33 | # Contributors
34 |
35 |
36 |
37 |
38 |
39 |
40 | Made with [contrib.rocks](https://contrib.rocks).
41 |
42 | # Credits
43 | This project is **MIT licensed** and entirely open source, hence, it is completely free to use. However, if you are inspired from this project and have used the source code of this project in your own projects, please consider giving credits to us.
44 | You can get the latest version of CutCode from the release page [here](https://github.com/CutCode-org/CutCode/releases/latest)
45 |
46 | **Thank you for using CutCode!**
47 | **Star and share this project with your programmer friends.**
48 |
--------------------------------------------------------------------------------
/imgs/add_page_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CutCode-org/CutCode/5d495274afa9041bce88831c73bfd10903895ff7/imgs/add_page_dark.png
--------------------------------------------------------------------------------
/imgs/banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CutCode-org/CutCode/5d495274afa9041bce88831c73bfd10903895ff7/imgs/banner.png
--------------------------------------------------------------------------------
/imgs/code_view_page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CutCode-org/CutCode/5d495274afa9041bce88831c73bfd10903895ff7/imgs/code_view_page.png
--------------------------------------------------------------------------------
/imgs/cutcode.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CutCode-org/CutCode/5d495274afa9041bce88831c73bfd10903895ff7/imgs/cutcode.gif
--------------------------------------------------------------------------------
/imgs/fav_page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CutCode-org/CutCode/5d495274afa9041bce88831c73bfd10903895ff7/imgs/fav_page.png
--------------------------------------------------------------------------------
/imgs/main_page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CutCode-org/CutCode/5d495274afa9041bce88831c73bfd10903895ff7/imgs/main_page.png
--------------------------------------------------------------------------------
/imgs/main_page_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CutCode-org/CutCode/5d495274afa9041bce88831c73bfd10903895ff7/imgs/main_page_light.png
--------------------------------------------------------------------------------
/imgs/main_page_search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CutCode-org/CutCode/5d495274afa9041bce88831c73bfd10903895ff7/imgs/main_page_search.png
--------------------------------------------------------------------------------
/imgs/setting_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CutCode-org/CutCode/5d495274afa9041bce88831c73bfd10903895ff7/imgs/setting_dark.png
--------------------------------------------------------------------------------
/imgs/setting_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CutCode-org/CutCode/5d495274afa9041bce88831c73bfd10903895ff7/imgs/setting_light.png
--------------------------------------------------------------------------------
/src/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/src/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Oo]ut/
33 | [Ll]og/
34 | [Ll]ogs/
35 |
36 | # Visual Studio 2015/2017 cache/options directory
37 | .vs/
38 | .idea/
39 | # Uncomment if you have tasks that create the project's static files in wwwroot
40 | #wwwroot/
41 |
42 | # Visual Studio 2017 auto generated files
43 | Generated\ Files/
44 |
45 | # MSTest test Results
46 | [Tt]est[Rr]esult*/
47 | [Bb]uild[Ll]og.*
48 |
49 | # NUnit
50 | *.VisualState.xml
51 | TestResult.xml
52 | nunit-*.xml
53 |
54 | # Build Results of an ATL Project
55 | [Dd]ebugPS/
56 | [Rr]eleasePS/
57 | dlldata.c
58 |
59 | # Benchmark Results
60 | BenchmarkDotNet.Artifacts/
61 |
62 | # .NET Core
63 | project.lock.json
64 | project.fragment.lock.json
65 | artifacts/
66 |
67 | # ASP.NET Scaffolding
68 | ScaffoldingReadMe.txt
69 |
70 | # StyleCop
71 | StyleCopReport.xml
72 |
73 | # Files built by Visual Studio
74 | *_i.c
75 | *_p.c
76 | *_h.h
77 | *.ilk
78 | *.meta
79 | *.obj
80 | *.iobj
81 | *.pch
82 | *.pdb
83 | *.ipdb
84 | *.pgc
85 | *.pgd
86 | *.rsp
87 | *.sbr
88 | *.tlb
89 | *.tli
90 | *.tlh
91 | *.tmp
92 | *.tmp_proj
93 | *_wpftmp.csproj
94 | *.log
95 | *.vspscc
96 | *.vssscc
97 | .builds
98 | *.pidb
99 | *.svclog
100 | *.scc
101 |
102 | # Chutzpah Test files
103 | _Chutzpah*
104 |
105 | # Visual C++ cache files
106 | ipch/
107 | *.aps
108 | *.ncb
109 | *.opendb
110 | *.opensdf
111 | *.sdf
112 | *.cachefile
113 | *.VC.db
114 | *.VC.VC.opendb
115 |
116 | # Visual Studio profiler
117 | *.psess
118 | *.vsp
119 | *.vspx
120 | *.sap
121 |
122 | # Visual Studio Trace Files
123 | *.e2e
124 |
125 | # TFS 2012 Local Workspace
126 | $tf/
127 |
128 | # Guidance Automation Toolkit
129 | *.gpState
130 |
131 | # ReSharper is a .NET coding add-in
132 | _ReSharper*/
133 | *.[Rr]e[Ss]harper
134 | *.DotSettings.user
135 |
136 | # TeamCity is a build add-in
137 | _TeamCity*
138 |
139 | # DotCover is a Code Coverage Tool
140 | *.dotCover
141 |
142 | # AxoCover is a Code Coverage Tool
143 | .axoCover/*
144 | !.axoCover/settings.json
145 |
146 | # Coverlet is a free, cross platform Code Coverage Tool
147 | coverage*.json
148 | coverage*.xml
149 | coverage*.info
150 |
151 | # Visual Studio code coverage results
152 | *.coverage
153 | *.coveragexml
154 |
155 | # NCrunch
156 | _NCrunch_*
157 | .*crunch*.local.xml
158 | nCrunchTemp_*
159 |
160 | # MightyMoose
161 | *.mm.*
162 | AutoTest.Net/
163 |
164 | # Web workbench (sass)
165 | .sass-cache/
166 |
167 | # Installshield output folder
168 | [Ee]xpress/
169 |
170 | # DocProject is a documentation generator add-in
171 | DocProject/buildhelp/
172 | DocProject/Help/*.HxT
173 | DocProject/Help/*.HxC
174 | DocProject/Help/*.hhc
175 | DocProject/Help/*.hhk
176 | DocProject/Help/*.hhp
177 | DocProject/Help/Html2
178 | DocProject/Help/html
179 |
180 | # Click-Once directory
181 | publish/
182 |
183 | # Publish Web Output
184 | *.[Pp]ublish.xml
185 | *.azurePubxml
186 | # Note: Comment the next line if you want to checkin your web deploy settings,
187 | # but database connection strings (with potential passwords) will be unencrypted
188 | *.pubxml
189 | *.publishproj
190 |
191 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
192 | # checkin your Azure Web App publish settings, but sensitive information contained
193 | # in these scripts will be unencrypted
194 | PublishScripts/
195 |
196 | # NuGet Packages
197 | *.nupkg
198 | # NuGet Symbol Packages
199 | *.snupkg
200 | # The packages folder can be ignored because of Package Restore
201 | **/[Pp]ackages/*
202 | # except build/, which is used as an MSBuild target.
203 | !**/[Pp]ackages/build/
204 | # Uncomment if necessary however generally it will be regenerated when needed
205 | #!**/[Pp]ackages/repositories.config
206 | # NuGet v3's project.json files produces more ignorable files
207 | *.nuget.props
208 | *.nuget.targets
209 |
210 | # Microsoft Azure Build Output
211 | csx/
212 | *.build.csdef
213 |
214 | # Microsoft Azure Emulator
215 | ecf/
216 | rcf/
217 |
218 | # Windows Store app package directories and files
219 | AppPackages/
220 | BundleArtifacts/
221 | Package.StoreAssociation.xml
222 | _pkginfo.txt
223 | *.appx
224 | *.appxbundle
225 | *.appxupload
226 |
227 | # Visual Studio cache files
228 | # files ending in .cache can be ignored
229 | *.[Cc]ache
230 | # but keep track of directories ending in .cache
231 | !?*.[Cc]ache/
232 |
233 | # Others
234 | ClientBin/
235 | ~$*
236 | *~
237 | *.dbmdl
238 | *.dbproj.schemaview
239 | *.jfm
240 | *.pfx
241 | *.publishsettings
242 | orleans.codegen.cs
243 |
244 | # Including strong name files can present a security risk
245 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
246 | #*.snk
247 |
248 | # Since there are multiple workflows, uncomment next line to ignore bower_components
249 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
250 | #bower_components/
251 |
252 | # RIA/Silverlight projects
253 | Generated_Code/
254 |
255 | # Backup & report files from converting an old project file
256 | # to a newer Visual Studio version. Backup files are not needed,
257 | # because we have git ;-)
258 | _UpgradeReport_Files/
259 | Backup*/
260 | UpgradeLog*.XML
261 | UpgradeLog*.htm
262 | ServiceFabricBackup/
263 | *.rptproj.bak
264 |
265 | # SQL Server files
266 | *.mdf
267 | *.ldf
268 | *.ndf
269 |
270 | # Business Intelligence projects
271 | *.rdl.data
272 | *.bim.layout
273 | *.bim_*.settings
274 | *.rptproj.rsuser
275 | *- [Bb]ackup.rdl
276 | *- [Bb]ackup ([0-9]).rdl
277 | *- [Bb]ackup ([0-9][0-9]).rdl
278 |
279 | # Microsoft Fakes
280 | FakesAssemblies/
281 |
282 | # GhostDoc plugin setting file
283 | *.GhostDoc.xml
284 |
285 | # Node.js Tools for Visual Studio
286 | .ntvs_analysis.dat
287 | node_modules/
288 |
289 | # Visual Studio 6 build log
290 | *.plg
291 |
292 | # Visual Studio 6 workspace options file
293 | *.opt
294 |
295 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
296 | *.vbw
297 |
298 | # Visual Studio LightSwitch build output
299 | **/*.HTMLClient/GeneratedArtifacts
300 | **/*.DesktopClient/GeneratedArtifacts
301 | **/*.DesktopClient/ModelManifest.xml
302 | **/*.Server/GeneratedArtifacts
303 | **/*.Server/ModelManifest.xml
304 | _Pvt_Extensions
305 |
306 | # Paket dependency manager
307 | .paket/paket.exe
308 | paket-files/
309 |
310 | # FAKE - F# Make
311 | .fake/
312 |
313 | # CodeRush personal settings
314 | .cr/personal
315 |
316 | # Python Tools for Visual Studio (PTVS)
317 | __pycache__/
318 | *.pyc
319 |
320 | # Cake - Uncomment if you are using it
321 | # tools/**
322 | # !tools/packages.config
323 |
324 | # Tabs Studio
325 | *.tss
326 |
327 | # Telerik's JustMock configuration file
328 | *.jmconfig
329 |
330 | # BizTalk build output
331 | *.btp.cs
332 | *.btm.cs
333 | *.odx.cs
334 | *.xsd.cs
335 |
336 | # OpenCover UI analysis results
337 | OpenCover/
338 |
339 | # Azure Stream Analytics local run output
340 | ASALocalRun/
341 |
342 | # MSBuild Binary and Structured Log
343 | *.binlog
344 |
345 | # NVidia Nsight GPU debugger configuration file
346 | *.nvuser
347 |
348 | # MFractors (Xamarin productivity tool) working folder
349 | .mfractor/
350 |
351 | # Local History for Visual Studio
352 | .localhistory/
353 |
354 | # BeatPulse healthcheck temp database
355 | healthchecksdb
356 |
357 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
358 | MigrationBackup/
359 |
360 | # Ionide (cross platform F# VS Code tools) working folder
361 | .ionide/
362 |
363 | # Fody - auto-generated XML schema
364 | FodyWeavers.xsd
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/App.axaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 | avares://CutCode.CrossPlatform/Assets/Fonts/Poppins-SemiBold.ttf#Poppins
12 | avares://CutCode.CrossPlatform/Assets/Fonts/Poppins-Regular.ttf#Poppins
13 | avares://CutCode.CrossPlatform/Assets/Fonts/Inconsolata-Regular.ttf#Inconsolata
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/App.axaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Drawing;
4 | using System.Threading;
5 | using Avalonia;
6 | using Avalonia.Controls.ApplicationLifetimes;
7 | using Avalonia.Markup.Xaml;
8 | using Avalonia.Markup.Xaml.Styling;
9 | using Avalonia.Media;
10 | using Avalonia.ReactiveUI;
11 | using CutCode.CrossPlatform.Helpers;
12 | using CutCode.CrossPlatform.ViewModels;
13 | using CutCode.CrossPlatform.Views;
14 | using CutCode.CrossPlatform.Services;
15 | using ReactiveUI;
16 | using Splat;
17 | using Color = Avalonia.Media.Color;
18 |
19 | namespace CutCode.CrossPlatform
20 | {
21 | public class App : Application
22 | {
23 | public override void Initialize()
24 | {
25 | AvaloniaXamlLoader.Load(this);
26 | }
27 |
28 | public override void OnFrameworkInitializationCompleted()
29 | {
30 | if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
31 | {
32 | if(ThemeService.Current.Theme == ThemeType.Light) SystemColorsConfig.LightThemeColors();
33 | else SystemColorsConfig.DarkThemeColors();
34 | ThemeService.Current.ThemeChanged += (sender, args) =>
35 | {
36 | if(ThemeService.Current.Theme == ThemeType.Light) SystemColorsConfig.LightThemeColors();
37 | else SystemColorsConfig.DarkThemeColors();
38 | };
39 |
40 | desktop.MainWindow = new MainWindow
41 | {
42 | DataContext = new MainWindowViewModel()
43 | };
44 |
45 | ThemeService.Current.Theme = DatabaseService.Current.Theme;
46 |
47 | desktop.Exit += (s, e) =>
48 | {
49 | DatabaseService.Current.ChangeTheme(ThemeService.Current.Theme);
50 | };
51 | var updateThread = new Thread(UpdateChecker.Run);
52 | updateThread.Start();
53 | }
54 | base.OnFrameworkInitializationCompleted();
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Assets/Fonts/Inconsolata-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CutCode-org/CutCode/5d495274afa9041bce88831c73bfd10903895ff7/src/CutCode.CrossPlatform/Assets/Fonts/Inconsolata-Regular.ttf
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Assets/Fonts/Poppins-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CutCode-org/CutCode/5d495274afa9041bce88831c73bfd10903895ff7/src/CutCode.CrossPlatform/Assets/Fonts/Poppins-Regular.ttf
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Assets/Fonts/Poppins-SemiBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CutCode-org/CutCode/5d495274afa9041bce88831c73bfd10903895ff7/src/CutCode.CrossPlatform/Assets/Fonts/Poppins-SemiBold.ttf
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Assets/Images/Developers/abdesol.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CutCode-org/CutCode/5d495274afa9041bce88831c73bfd10903895ff7/src/CutCode.CrossPlatform/Assets/Images/Developers/abdesol.png
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Assets/Images/Developers/piero.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CutCode-org/CutCode/5d495274afa9041bce88831c73bfd10903895ff7/src/CutCode.CrossPlatform/Assets/Images/Developers/piero.png
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Assets/Images/logo.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CutCode-org/CutCode/5d495274afa9041bce88831c73bfd10903895ff7/src/CutCode.CrossPlatform/Assets/Images/logo.ico
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Assets/Images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CutCode-org/CutCode/5d495274afa9041bce88831c73bfd10903895ff7/src/CutCode.CrossPlatform/Assets/Images/logo.png
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Assets/avalonia-logo.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CutCode-org/CutCode/5d495274afa9041bce88831c73bfd10903895ff7/src/CutCode.CrossPlatform/Assets/avalonia-logo.ico
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/BootStrappers/EntryBootstrapper.cs:
--------------------------------------------------------------------------------
1 | // ---------------------------------------------
2 | // --- CutCode.CrossPlatform by Scarementus ---
3 | // --- Licence MIT ---
4 | // ---------------------------------------------
5 |
6 | using Splat;
7 |
8 | namespace CutCode.CrossPlatform.BootStrappers;
9 |
10 | public static class EntryBootstrapper
11 | {
12 | public static void Register(IMutableDependencyResolver services, IReadonlyDependencyResolver resolver)
13 | {
14 | ServicesBootstrapper.RegisterServices(services, resolver);
15 | NavigationBootstrapper.RegisterViewModels(services, resolver);
16 | }
17 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/BootStrappers/NavigationBootstrapper.cs:
--------------------------------------------------------------------------------
1 | // ---------------------------------------------
2 | // --- CutCode.CrossPlatform by Scarementus ---
3 | // --- Licence MIT ---
4 | // ---------------------------------------------
5 |
6 | using CutCode.CrossPlatform.ViewModels;
7 | using CutCode.CrossPlatform.Views;
8 | using ReactiveUI;
9 | using Splat;
10 |
11 | namespace CutCode.CrossPlatform.BootStrappers;
12 |
13 | public static class NavigationBootstrapper
14 | {
15 | public static void RegisterViewModels(IMutableDependencyResolver services, IReadonlyDependencyResolver resolver)
16 | {
17 | services.Register(() => new HomeView(), typeof(IViewFor));
18 | services.Register(() => new AddView(), typeof(IViewFor));
19 | services.Register(() => new FavoritesView(), typeof(IViewFor));
20 | services.Register(() => new SettingsView(), typeof(IViewFor));
21 | services.Register(() => new CodeView(), typeof(IViewFor));
22 | }
23 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/BootStrappers/ServicesBootstrapper.cs:
--------------------------------------------------------------------------------
1 | // ---------------------------------------------
2 | // --- CutCode.CrossPlatform by Scarementus ---
3 | // --- Licence MIT ---
4 | // ---------------------------------------------
5 |
6 | using Splat;
7 |
8 | namespace CutCode.CrossPlatform.BootStrappers;
9 |
10 | public class ServicesBootstrapper
11 | {
12 | public static void RegisterServices(IMutableDependencyResolver services, IReadonlyDependencyResolver resolver)
13 | {
14 | }
15 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Controls/AnimatedListBox.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Avalonia;
4 | using Avalonia.Controls;
5 | using Avalonia.Controls.Generators;
6 | using Avalonia.Controls.Metadata;
7 | using Avalonia.Styling;
8 | using AvaloniaEdit;
9 |
10 | namespace CutCode.CrossPlatform.Controls;
11 |
12 | public class AnimatedListBox : ListBox, IStyleable
13 | {
14 | Type IStyleable.StyleKey => typeof(ListBox);
15 |
16 | protected override IItemContainerGenerator CreateItemContainerGenerator()
17 | {
18 | return new ItemContainerGenerator(
19 | this,
20 | AnimatedListBoxItem.ContentProperty,
21 | AnimatedListBoxItem.ContentTemplateProperty);
22 | }
23 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Controls/AnimatedListBoxItem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using Avalonia;
4 | using Avalonia.Animation;
5 | using Avalonia.Controls;
6 | using Avalonia.Controls.Metadata;
7 | using Avalonia.Input;
8 | using Avalonia.LogicalTree;
9 | using Avalonia.Styling;
10 | using Microsoft.CodeAnalysis.CSharp.Syntax;
11 |
12 | namespace CutCode.CrossPlatform.Controls;
13 |
14 | [PseudoClasses(":Added", ":Removed")]
15 | public class AnimatedListBoxItem : ListBoxItem, IStyleable
16 | {
17 | public AnimatedListBoxItem()
18 | {
19 | }
20 | Type IStyleable.StyleKey => typeof(AnimatedListBoxItem);
21 |
22 | private bool isAttached = false;
23 | protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
24 | {
25 | if (isAttached) return;
26 | PseudoClasses.Set(":Added", true);
27 | isAttached = true;
28 | base.OnAttachedToVisualTree(e);
29 | }
30 |
31 | protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
32 | {
33 | PseudoClasses.Set(":Removed", true);
34 | base.OnDetachedFromVisualTree(e);
35 | }
36 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Controls/CustomComboBox.axaml:
--------------------------------------------------------------------------------
1 |
7 |
9 |
13 |
19 |
20 |
32 |
33 |
34 |
42 |
47 |
56 |
63 |
64 |
70 |
73 |
75 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
92 |
95 |
98 |
99 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Controls/CustomComboBox.axaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Windows.Input;
4 | using Avalonia;
5 | using Avalonia.Controls;
6 | using Avalonia.Data;
7 | using Avalonia.Markup.Xaml;
8 | using Avalonia.Media;
9 | using CutCode.CrossPlatform.Helpers;
10 |
11 | namespace CutCode.CrossPlatform.Controls
12 | {
13 | public class CustomComboBox : UserControl
14 | {
15 | private Label nameLabel;
16 | private ComboBox comboBox;
17 |
18 | static CustomComboBox()
19 | {
20 | BackgroundProperty.Changed.Subscribe(BackgroundPropertyChanged);
21 | ForegroundProperty.Changed.Subscribe(ForegroundPropertyChanged);
22 | OverlayBrushProperty.Changed.Subscribe(OverlayBrushPropertyChanged);
23 |
24 | NameProperty.Changed.Subscribe(NamePropertyChanged);
25 | ItemsProperty.Changed.Subscribe(ItemsPropertyChanged);
26 | SelectedIndexProperty.Changed.Subscribe(SelectedIndexPropertyChanged);
27 | }
28 |
29 | public CustomComboBox()
30 | {
31 | InitializeComponent();
32 | this.GetControl("nameLabel", out nameLabel);
33 | this.GetControl("comboBox", out comboBox);
34 |
35 | comboBox.SelectionChanged += (sender, e) =>
36 | {
37 | ItemSelected?.Execute((sender as ComboBox)?.SelectedItem as string);
38 | };
39 | }
40 |
41 | private void InitializeComponent()
42 | {
43 | AvaloniaXamlLoader.Load(this);
44 | }
45 |
46 | public new static readonly StyledProperty BackgroundProperty =
47 | AvaloniaProperty.Register(nameof(Background));
48 |
49 | public new IBrush Background
50 | {
51 | get => GetValue(BackgroundProperty);
52 | set => SetValue(BackgroundProperty, value);
53 | }
54 |
55 | private static void BackgroundPropertyChanged(AvaloniaPropertyChangedEventArgs e)
56 | {
57 | if (e.Sender is CustomComboBox ctrl)
58 | {
59 | ctrl.comboBox.Background = e.NewValue.Value;
60 | }
61 | }
62 |
63 | public new static readonly StyledProperty ForegroundProperty =
64 | AvaloniaProperty.Register(nameof(Foreground));
65 |
66 | public new IBrush Foreground
67 | {
68 | get => GetValue(ForegroundProperty);
69 | set => SetValue(ForegroundProperty, value);
70 | }
71 |
72 | private static void ForegroundPropertyChanged(AvaloniaPropertyChangedEventArgs e)
73 | {
74 | if (e.Sender is CustomComboBox ctrl)
75 | {
76 | ctrl.nameLabel.Foreground = e.NewValue.Value;
77 | ctrl.comboBox.Foreground = e.NewValue.Value;
78 | }
79 | }
80 |
81 | public new static readonly StyledProperty OverlayBrushProperty =
82 | AvaloniaProperty.Register(nameof(OverlayBrush));
83 |
84 | public new IBrush OverlayBrush
85 | {
86 | get => GetValue(OverlayBrushProperty);
87 | set => SetValue(OverlayBrushProperty, value);
88 | }
89 |
90 | private static void OverlayBrushPropertyChanged(AvaloniaPropertyChangedEventArgs e)
91 | {
92 | if (e.Sender is CustomComboBox ctrl)
93 | {
94 | ctrl.comboBox.BorderBrush = e.NewValue.Value;
95 | }
96 | }
97 |
98 | public static readonly StyledProperty NameProperty =
99 | AvaloniaProperty.Register(nameof(Name), defaultValue:"Combo Box");
100 |
101 | public string Name
102 | {
103 | get => GetValue(NameProperty);
104 | set => SetValue(NameProperty, value);
105 | }
106 |
107 | private static void NamePropertyChanged(AvaloniaPropertyChangedEventArgs e)
108 | {
109 | if (e.Sender is CustomComboBox ctrl)
110 | {
111 | ctrl.nameLabel.Content = e.NewValue.Value;
112 | }
113 | }
114 |
115 | public new static readonly StyledProperty> ItemsProperty =
116 | AvaloniaProperty.Register>(nameof(Items));
117 |
118 | public IList Items
119 | {
120 | get => GetValue(ItemsProperty);
121 | set => SetValue(ItemsProperty, value);
122 | }
123 |
124 | private static void ItemsPropertyChanged(AvaloniaPropertyChangedEventArgs> e)
125 | {
126 | if (e.Sender is CustomComboBox ctrl)
127 | {
128 | ctrl.comboBox.Items = e.NewValue.Value;
129 | }
130 | }
131 |
132 | public new static readonly StyledProperty ItemSelectedProperty =
133 | AvaloniaProperty.Register(nameof(ItemSelected));
134 |
135 | public ICommand ItemSelected
136 | {
137 | get => GetValue(ItemSelectedProperty);
138 | set => SetValue(ItemSelectedProperty, value);
139 | }
140 |
141 | public static readonly StyledProperty SelectedIndexProperty =
142 | AvaloniaProperty.Register(nameof(SelectedIndex), defaultValue:-1, defaultBindingMode:BindingMode.TwoWay);
143 |
144 | public int SelectedIndex
145 | {
146 | get => GetValue(SelectedIndexProperty);
147 | set => SetValue(SelectedIndexProperty, value);
148 | }
149 |
150 | private static void SelectedIndexPropertyChanged(AvaloniaPropertyChangedEventArgs e)
151 | {
152 | if (e.Sender is CustomComboBox ctrl)
153 | {
154 | ctrl.comboBox.SelectedIndex = e.NewValue.Value;
155 | }
156 | }
157 | }
158 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Controls/CustomSearchBar.axaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Controls/CustomSearchBar.axaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Reactive.Linq;
3 | using System.Windows.Input;
4 | using Avalonia;
5 | using Avalonia.Controls;
6 | using Avalonia.Data;
7 | using Avalonia.Interactivity;
8 | using Avalonia.Markup.Xaml;
9 | using Avalonia.Media;
10 | using CutCode.CrossPlatform.Helpers;
11 | using CutCode.CrossPlatform.Services;
12 | using ReactiveUI;
13 |
14 | namespace CutCode.CrossPlatform.Controls
15 | {
16 | public class CustomSearchBar : UserControl
17 | {
18 | private TextBox textBox;
19 | private ProgressBar progressBar;
20 | private Button CloseButton;
21 | private Grid panel;
22 | static CustomSearchBar()
23 | {
24 | BackgroundProperty.Changed.Subscribe(BackgroundPropertyChanged);
25 | ForegroundProperty.Changed.Subscribe(ForegroundPropertyChanged);
26 | OverlayBrushProperty.Changed.Subscribe(OverlayBrushPropertyChanged);
27 | TextProperty.Changed.Subscribe(TextPropertyChanged);
28 | PlaceHolderTextProperty.Changed.Subscribe(PlaceHolderTextPropertyChanged);
29 | IsSearchBusyProperty.Changed.Subscribe(IsSearchBusyPropertyChanged);
30 | }
31 | public CustomSearchBar()
32 | {
33 | InitializeComponent();
34 | this.GetControl("textBox", out textBox);
35 | this.GetControl("progressBar", out progressBar);
36 | this.GetControl("CloseButton", out CloseButton);
37 | this.GetControl("panel", out panel);
38 |
39 | textBox.DataContext = this;
40 | progressBar.IsVisible = false;
41 |
42 | CloseButton.Foreground = ThemeService.Current.Theme == ThemeType.Light ? Brushes.Black : Brushes.White;
43 | ThemeService.Current.ThemeChanged += (sender, args) =>
44 | {
45 | var service = (ThemeService)sender!;
46 | textBox.CaretBrush = ThemeService.Current.Theme == ThemeType.Light ? Brushes.Black : Brushes.White;
47 | CloseButton.Foreground = ThemeService.Current.Theme == ThemeType.Light ? Brushes.Black : Brushes.White;
48 | };
49 |
50 | this.WhenAnyValue(x => x.textBox.Text)
51 | .Throttle(TimeSpan.FromMilliseconds(700))
52 | .ObserveOn(RxApp.MainThreadScheduler)
53 | .Subscribe(SearchActivate!);
54 |
55 | CloseButton.Click += CloseButtonOnClick;
56 | }
57 |
58 | private void CloseButtonOnClick(object? sender, RoutedEventArgs e)
59 | {
60 | textBox.Clear();
61 | Text = string.Empty;
62 | CloseButton.IsVisible = false;
63 | SearchCancelled?.Execute(null);
64 | }
65 |
66 | private void InitializeComponent()
67 | {
68 | AvaloniaXamlLoader.Load(this);
69 | }
70 |
71 | private string _oldText = "";
72 | private async void SearchActivate(string s)
73 | {
74 | if (string.IsNullOrWhiteSpace(s) || s == _oldText)
75 | {
76 | IsSearchBusy = false;
77 | CloseButton.IsVisible = false;
78 | SearchCancelled?.Execute(s);
79 | return;
80 | }
81 | CloseButton.IsVisible = true;
82 | _oldText = s;
83 | SearchCommand?.Execute(s);
84 | }
85 |
86 | public new static readonly StyledProperty BackgroundProperty =
87 | AvaloniaProperty.Register(nameof(Background));
88 |
89 | public new IBrush Background
90 | {
91 | get => GetValue(BackgroundProperty);
92 | set => SetValue(BackgroundProperty, value);
93 | }
94 |
95 | private static void BackgroundPropertyChanged(AvaloniaPropertyChangedEventArgs e)
96 | {
97 | if (e.Sender is CustomSearchBar ctrl)
98 | {
99 | ctrl.textBox.Background = e.NewValue.Value;
100 | ctrl.panel.Background = e.NewValue.Value;
101 | }
102 | }
103 |
104 | public new static readonly StyledProperty ForegroundProperty =
105 | AvaloniaProperty.Register(nameof(Foreground));
106 |
107 | public new IBrush Foreground
108 | {
109 | get => GetValue(ForegroundProperty);
110 | set => SetValue(ForegroundProperty, value);
111 | }
112 |
113 | private static void ForegroundPropertyChanged(AvaloniaPropertyChangedEventArgs e)
114 | {
115 | if (e.Sender is CustomSearchBar ctrl)
116 | {
117 | ctrl.textBox.Foreground = e.NewValue.Value;
118 | }
119 | }
120 |
121 | public new static readonly StyledProperty OverlayBrushProperty =
122 | AvaloniaProperty.Register(nameof(OverlayBrush));
123 |
124 | public new IBrush OverlayBrush
125 | {
126 | get => GetValue(OverlayBrushProperty);
127 | set => SetValue(OverlayBrushProperty, value);
128 | }
129 |
130 | private static void OverlayBrushPropertyChanged(AvaloniaPropertyChangedEventArgs e)
131 | {
132 | if (e.Sender is CustomSearchBar ctrl)
133 | {
134 | ctrl.textBox.BorderBrush = e.NewValue.Value;
135 | }
136 | }
137 |
138 | public new static readonly StyledProperty TextProperty =
139 | AvaloniaProperty.Register(nameof(TextProperty), defaultBindingMode: BindingMode.TwoWay);
140 |
141 | public new string Text
142 | {
143 | get => GetValue(TextProperty);
144 | set => SetValue(TextProperty, value);
145 | }
146 |
147 | private static void TextPropertyChanged(AvaloniaPropertyChangedEventArgs e)
148 | {
149 | if (e.Sender is CustomSearchBar ctrl)
150 | {
151 | ctrl.textBox.Text = e.NewValue.Value;
152 | }
153 | }
154 |
155 | public new static readonly StyledProperty PlaceHolderTextProperty =
156 | AvaloniaProperty.Register(nameof(PlaceHolderText));
157 |
158 | public new string PlaceHolderText
159 | {
160 | get => GetValue(PlaceHolderTextProperty);
161 | set => SetValue(PlaceHolderTextProperty, value);
162 | }
163 |
164 | private static void PlaceHolderTextPropertyChanged(AvaloniaPropertyChangedEventArgs e)
165 | {
166 | if (e.Sender is CustomSearchBar ctrl)
167 | {
168 | ctrl.textBox.Watermark = e.NewValue.Value;
169 | }
170 | }
171 |
172 | public new static readonly StyledProperty SearchCommandProperty =
173 | AvaloniaProperty.Register(nameof(SearchCommand));
174 | public ICommand SearchCommand
175 | {
176 | get => GetValue(SearchCommandProperty);
177 | set => SetValue(SearchCommandProperty, value);
178 | }
179 |
180 | public new static readonly StyledProperty SearchCancelledProperty =
181 | AvaloniaProperty.Register(nameof(SearchCancelled));
182 | public ICommand SearchCancelled
183 | {
184 | get => GetValue(SearchCancelledProperty);
185 | set => SetValue(SearchCancelledProperty, value);
186 | }
187 |
188 | public new static readonly StyledProperty IsSearchBusyProperty =
189 | AvaloniaProperty.Register(nameof(IsSearchBusy));
190 |
191 | public bool IsSearchBusy
192 | {
193 | get => GetValue(IsSearchBusyProperty);
194 | set => SetValue(IsSearchBusyProperty, value);
195 | }
196 |
197 | private static void IsSearchBusyPropertyChanged(AvaloniaPropertyChangedEventArgs e)
198 | {
199 | if (e.Sender is CustomSearchBar ctrl)
200 | {
201 | ctrl.progressBar.IsVisible = e.NewValue.Value;
202 | }
203 | }
204 | }
205 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Controls/NavigationItem.axaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
18 |
22 |
25 |
26 |
27 |
28 |
30 |
35 |
36 |
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Controls/NavigationItem.axaml.cs:
--------------------------------------------------------------------------------
1 | // ---------------------------------------------
2 | // --- CutCode.CrossPlatform by Scarementus ---
3 | // --- Licence MIT ---
4 | // ---------------------------------------------
5 |
6 | using System.Windows.Input;
7 | using Aura.UI.Extensions;
8 | using Avalonia;
9 | using Avalonia.Controls;
10 | using Avalonia.Controls.Shapes;
11 | using Avalonia.Interactivity;
12 | using Avalonia.Markup.Xaml;
13 | using Avalonia.Media;
14 | using Avalonia.Xaml.Interactions.Custom;
15 |
16 | namespace CutCode.CrossPlatform.Controls;
17 |
18 | public class NavigationItem : UserControl
19 | {
20 | private Path IconPath => this.FindControl(nameof(IconPath));
21 |
22 | private Border ActiveBorder => this.FindControl(nameof(ActiveBorder));
23 |
24 | private Button MainButton => this.FindControl
80 |
81 |
82 |
83 |
84 |
85 |
88 |
89 |
93 |
97 |
100 |
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Styles/ScrollBarStyles.axaml:
--------------------------------------------------------------------------------
1 |
3 |
21 |
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Styles/TextBoxStyles.axaml:
--------------------------------------------------------------------------------
1 |
3 |
7 |
11 |
14 |
18 |
19 |
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/ViewLocator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Avalonia.Controls;
3 | using Avalonia.Controls.Templates;
4 | using CutCode.CrossPlatform.ViewModels;
5 |
6 | namespace CutCode.CrossPlatform
7 | {
8 | public class ViewLocator : IDataTemplate
9 | {
10 | public IControl Build(object data)
11 | {
12 | var name = data.GetType().FullName!.Replace("ViewModel", "View");
13 | var type = Type.GetType(name);
14 |
15 | if (type != null)
16 | {
17 | return (Control)Activator.CreateInstance(type)!;
18 | }
19 | else
20 | {
21 | return new TextBlock { Text = "Not Found: " + name };
22 | }
23 | }
24 |
25 | public bool Match(object data)
26 | {
27 | return data is ViewModelBase;
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/ViewModels/AddViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.Linq;
5 | using System.Text;
6 | using Avalonia.Media;
7 | using AvaloniaEdit.TextMate.Grammars;
8 | using CutCode.CrossPlatform.Helpers;
9 | using CutCode.CrossPlatform.Models;
10 | using CutCode.CrossPlatform.Services;
11 | using ReactiveUI;
12 | using ReactiveUI.Fody.Helpers;
13 |
14 | namespace CutCode.CrossPlatform.ViewModels;
15 |
16 | public class AddViewModel : PageBaseViewModel, IRoutableViewModel
17 | {
18 | private string _selectedLanguage;
19 |
20 | public AddViewModel()
21 | {
22 | AllLangs = new ObservableCollection
23 | {
24 | "All languages", "Python", "C++", "C#", "CSS", "Dart", "Golang", "Html", "Java",
25 | "Javascript", "Kotlin", "Php", "C", "Ruby", "Rust", "Sql", "Swift"
26 | };
27 |
28 | Cells = new ObservableCollection();
29 | IsCellEmpty = true;
30 | Cells.CollectionChanged += (sender, args) => { IsCellEmpty = Cells.Count == 0; };
31 | }
32 |
33 | public AddViewModel(IScreen screen)
34 | {
35 | HostScreen = screen;
36 | AllLangs = new ObservableCollection
37 | {
38 | "All languages", "Python", "C++", "C#", "CSS", "Dart", "Golang", "Html", "Java",
39 | "Javascript", "Kotlin", "Php", "C", "Ruby", "Rust", "Sql", "Swift"
40 | };
41 |
42 | Cells = new ObservableCollection();
43 | IsCellEmpty = true;
44 | Cells.CollectionChanged += (sender, args) => { IsCellEmpty = Cells.Count == 0; };
45 |
46 | RegistryOptions reg =
47 | new RegistryOptions(ThemeService.Theme == ThemeType.Light ? ThemeName.LightPlus : ThemeName.DarkPlus);
48 |
49 | AllLanguages = new ObservableCollection(reg.GetAvailableLanguages());
50 | SelectedLanguage2 = reg.GetLanguageByExtension(".cs");
51 | this.WhenAnyValue(x => x.SelectedLanguage2).WhereNotNull().Subscribe(GlobalEvents.LanguageSet);
52 | }
53 |
54 | [Reactive] public ObservableCollection AllLanguages { get; set; }
55 |
56 | [Reactive] public Language SelectedLanguage2 { get; set; }
57 |
58 | public ObservableCollection Cells { get; }
59 | public IList AllLangs { get; set; }
60 |
61 | [Reactive] public bool IsCellEmpty { get; set; }
62 |
63 | [Reactive] public string Title { get; set; }
64 |
65 | [Reactive] public Color BackgroundColor { get; set; }
66 |
67 | [Reactive] public Color ComboBoxBackground { get; set; }
68 |
69 | [Reactive] public Color ComboBoxBackgroundOnHover { get; set; }
70 |
71 | [Reactive] public Color BarBackground { get; set; }
72 |
73 | [Reactive] public Color TextAreaBackground { get; set; }
74 |
75 | [Reactive] public Color TextAreaForeground { get; set; }
76 |
77 | [Reactive] public Color TextAreaOverlayBackground { get; set; }
78 |
79 | public string? UrlPathSegment => Guid.NewGuid().ToString().Substring(0, 5);
80 | public IScreen HostScreen { get; }
81 |
82 | protected override void OnLightThemeIsSet()
83 | {
84 | BackgroundColor = Color.Parse("#FCFCFC");
85 | BarBackground = Color.Parse("#F6F6F6");
86 |
87 | TextAreaBackground = Color.Parse("#ECECEC");
88 | TextAreaForeground = Color.Parse("#000000");
89 | TextAreaOverlayBackground = Color.Parse("#E2E2E2");
90 |
91 | ComboBoxBackground = Color.Parse("#ECECEC");
92 | ComboBoxBackgroundOnHover = Color.Parse("#E2E2E2");
93 | }
94 |
95 | protected override void OnDarkThemeIsSet()
96 | {
97 | BackgroundColor = Color.Parse("#36393F");
98 | BarBackground = Color.Parse("#303338");
99 |
100 | TextAreaBackground = Color.Parse("#2A2E33");
101 | TextAreaForeground = Color.Parse("#FFFFFF");
102 | TextAreaOverlayBackground = Color.Parse("#24272B");
103 |
104 | ComboBoxBackground = Color.Parse("#2A2E33");
105 | ComboBoxBackgroundOnHover = Color.Parse("#24272B");
106 | }
107 |
108 | public async void AddCell()
109 | {
110 | Cells.Add(new CodeCellViewModel(this));
111 | // the problem is after this async block ends.
112 | }
113 |
114 | public async void Cancel()
115 | {
116 | Cells.Clear();
117 | GlobalEvents.CancelClicked();
118 | }
119 |
120 | public async void Save()
121 | {
122 | StringBuilder? error = new();
123 | if (string.IsNullOrEmpty(Title))
124 | error.AppendLine("Title cannot be empty");
125 | if (Cells.Count > 0)
126 | {
127 | if (Cells.Select(x => x.Description).ToList().Any(string.IsNullOrEmpty))
128 | error.AppendLine("The Description for the cells cannot be empty");
129 | if (Cells.Select(x => x.Document.Text).ToList().Any(string.IsNullOrEmpty))
130 | error.AppendLine("The Code text cannot be empty");
131 | }
132 |
133 | if (error.Length == 0)
134 | {
135 | var cellsList = Cells.Select(x =>
136 | new Dictionary
137 | {
138 | { "Description", x.Description },
139 | { "Code", x.Document.Text }
140 | }).ToList();
141 |
142 | CodeModel codeModel = DataBase.AddCode(Title, cellsList, SelectedLanguage2.Extensions.First());
143 | GlobalEvents.ShowCodeModel(codeModel);
144 | Title = "";
145 | Cells.Clear();
146 | NotificationService.CreateNotification("Notification", "New code is successfully created", 3);
147 | }
148 | else
149 | {
150 | NotificationService.CreateNotification("Warning", error.ToString(), 5);
151 | }
152 | }
153 |
154 | public async void LanguageChanged(string selectedLanguage)
155 | {
156 | _selectedLanguage = selectedLanguage;
157 | }
158 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/ViewModels/CodeCardViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reactive;
5 | using Avalonia.Media;
6 | using CutCode.CrossPlatform.Helpers;
7 | using CutCode.CrossPlatform.Models;
8 | using CutCode.CrossPlatform.Services;
9 | using CutCode.CrossPlatform.Views;
10 | using DynamicData;
11 | using Newtonsoft.Json;
12 | using ReactiveUI;
13 | using ReactiveUI.Fody.Helpers;
14 | using TextMateSharp.Grammars;
15 |
16 | namespace CutCode.CrossPlatform.ViewModels;
17 |
18 | public class CodeCardViewModel : ViewModelBase
19 | {
20 | public CodeModel Code;
21 | private RegistryOptions _registryOptions;
22 |
23 | public CodeCardViewModel(CodeModel code)
24 | {
25 | Initialise(code);
26 | }
27 |
28 | public void Initialise(CodeModel code)
29 | {
30 | _registryOptions = new(ThemeService.Current.Theme == ThemeType.Light ? ThemeName.LightPlus : ThemeName.DarkPlus);
31 | Navigate = ReactiveCommand.Create(Clicked);
32 | Code = code;
33 | Title = code.Title;
34 | LastModificationTime = code.LastModificationTime;
35 | Language = code.Language;
36 | IsFavouritePath = code.IsFavourite ? IconPaths.StarFull : IconPaths.Star;
37 | FavouriteText = Code.IsFavourite ? "Remove from favourite" : "Add to favourite";
38 |
39 | if (ThemeService.Current.Theme == ThemeType.Light) OnLightThemeIsSet();
40 | else OnDarkThemeIsSet();
41 |
42 | ThemeService.Current.ThemeChanged += (sender, args) =>
43 | {
44 | if (ThemeService.Current.Theme == ThemeType.Light) OnLightThemeIsSet();
45 | else OnDarkThemeIsSet();
46 | };
47 |
48 | SetDescription(code.Cells);
49 | IsPopupOpen = false;
50 |
51 | DatabaseService.Current.AllCodesUpdated += (sender, args) =>
52 | {
53 | if (DatabaseService.Current.AllCodes.Count > 0)
54 | {
55 | CodeModel? currentCode = DatabaseService.Current.AllCodes.Find(c => c.Id == Code.Id);
56 | if (currentCode is not null)
57 | {
58 | FavouriteText = currentCode.IsFavourite ? "Remove from favourite" : "Add to favourite";
59 | if (ThemeService.Current.Theme == ThemeType.Light)
60 | IsFavouriteColor =
61 | currentCode.IsFavourite ? Color.Parse("#F7A000") : Color.Parse("#4D4D4D");
62 | else
63 | IsFavouriteColor =
64 | currentCode.IsFavourite ? Color.Parse("#F7A000") : Color.Parse("#94969A");
65 | IsFavouritePath = currentCode.IsFavourite ? IconPaths.StarFull : IconPaths.Star;
66 | Code = currentCode;
67 | }
68 | }
69 | };
70 | }
71 |
72 | [Reactive] public Color MainTextColor { get; set; }
73 |
74 | [Reactive] public Color CardColor { get; set; }
75 |
76 | [Reactive] public Color PopupColor { get; set; }
77 |
78 | [Reactive] public Color CardColorHover { get; set; }
79 |
80 | [Reactive] public Color LanguageColor { get; set; }
81 |
82 | public int Id { get; set; }
83 |
84 | [Reactive] public string Title { get; set; }
85 |
86 | [Reactive] public string Description { get; set; }
87 |
88 | [Reactive] public string FavouriteText { get; set; }
89 |
90 | [Reactive] public string IsFavouritePath { get; set; }
91 |
92 | [Reactive] public bool IsPopupOpen { get; set; }
93 |
94 | [Reactive] public Color IsFavouriteColor { get; set; }
95 |
96 | public string LanguagePath =>
97 | Languages.GetLanguagePath(_registryOptions.GetLanguageByExtension(Language));
98 |
99 | public string Language { get; set; }
100 | public long LastModificationTime { get; set; }
101 |
102 | private void OnLightThemeIsSet()
103 | {
104 | MainTextColor = Color.Parse("#0B0B13");
105 | LanguageColor = Color.Parse("#4D4D4D");
106 | CardColor = Color.Parse("#F2F3F5");
107 | PopupColor = Color.Parse("#CECECE");
108 | CardColorHover = Color.Parse("#E1E1E1");
109 | IsFavouriteColor = Code.IsFavourite ? Color.Parse("#F7A000") : Color.Parse("#4D4D4D");
110 | }
111 |
112 | private void OnDarkThemeIsSet()
113 | {
114 | MainTextColor = Color.Parse("#E8E8E8");
115 | LanguageColor = Color.Parse("#94969A");
116 | CardColor = Color.Parse("#2F3136");
117 | PopupColor = Color.Parse("#26272B");
118 | CardColorHover = Color.Parse("#282A2E");
119 | IsFavouriteColor = Code.IsFavourite ? Color.Parse("#F7A000") : Color.Parse("#94969A");
120 | }
121 |
122 | private void SetDescription(string _cells)
123 | {
124 | var cells = JsonConvert.DeserializeObject>>(_cells);
125 | var descriptions = cells.Select(x => x["Description"]);
126 |
127 | Description = "";
128 | int i = 0;
129 | foreach (string description in descriptions)
130 | {
131 | if (i == 0) Description += $"● {description}";
132 | else Description += $"\n● {description}";
133 | i++;
134 | }
135 | }
136 |
137 | public ReactiveCommand Navigate { get; set; }
138 |
139 | public void Clicked()
140 | {
141 | GlobalEvents.ShowCodeModel(Code);
142 | // _router.Navigate.Execute(new CodeViewModel(Code, HostScreen));
143 | // PageService.Current.ExternalPage = new CodeView
144 | // {
145 | // DataContext = new CodeViewModel(Code)
146 | // };
147 | }
148 |
149 |
150 | public async void Favourite()
151 | {
152 | IsPopupOpen = false;
153 | Code.IsFavourite = !Code.IsFavourite;
154 | DatabaseService.Current.FavModify(Code);
155 | }
156 |
157 | public async void Share()
158 | {
159 | // code sharing will be implemented later
160 | }
161 |
162 | public async void Delete()
163 | {
164 | IsPopupOpen = false;
165 | bool delete = DatabaseService.Current.DelCode(Code);
166 | if (!delete)
167 | NotificationService.Current.CreateNotification("Error", "Error, Unable to delete the code!", 3);
168 | }
169 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/ViewModels/CodeCellViewModel.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Media;
2 | using AvaloniaEdit.Document;
3 | using AvaloniaEdit.TextMate.Grammars;
4 | using CutCode.CrossPlatform.Helpers;
5 | using ReactiveUI.Fody.Helpers;
6 |
7 | namespace CutCode.CrossPlatform.ViewModels;
8 |
9 | public class CodeCellViewModel : PageBaseViewModel
10 | {
11 | private readonly AddViewModel AddViewModelInstance;
12 | private readonly CodeViewModel CodeViewModelInstance;
13 | private readonly bool isFromAddPage;
14 | [Reactive] public TextDocument Document { get; set; } = new TextDocument();
15 |
16 | public CodeCellViewModel(AddViewModel viewModelInstance)
17 | {
18 | // Creating new one
19 | AddViewModelInstance = viewModelInstance;
20 | IsEditable = true;
21 | IsMoreClickable = false;
22 | Code = "";
23 | isFromAddPage = true;
24 | }
25 |
26 | public CodeCellViewModel(CodeViewModel viewModelInstance)
27 | {
28 | // Creating new one
29 | CodeViewModelInstance = viewModelInstance;
30 | IsEditable = true;
31 | IsMoreClickable = false;
32 | Code = "";
33 | isFromAddPage = false;
34 | }
35 |
36 | public CodeCellViewModel(CodeViewModel viewModelInstance, string description, string code)
37 | {
38 | // if we are fetching from database
39 | CodeViewModelInstance = viewModelInstance;
40 | Description = description;
41 | Code = code;
42 | Document.Text = code;
43 |
44 | IsEditable = false;
45 | IsMoreClickable = true;
46 | isFromAddPage = false;
47 |
48 | GlobalEvents.OnViewRegistered += (sender, o) =>
49 | {
50 | GlobalEvents.LanguageSet(viewModelInstance._language);
51 | };
52 | }
53 |
54 | [Reactive] public string Description { get; set; }
55 |
56 | [Reactive] public string Code { get; set; }
57 |
58 | [Reactive] public bool IsEditable { get; set; }
59 |
60 | [Reactive] public bool IsMoreClickable { get; set; }
61 |
62 | [Reactive] public Color Background { get; set; }
63 |
64 | [Reactive] public Color TextColor { get; set; }
65 |
66 | [Reactive] public Color BtnColor { get; set; }
67 |
68 | protected override void OnLightThemeIsSet()
69 | {
70 | Background = Color.Parse("#E3E5E8");
71 | TextColor = Color.Parse("#000000");
72 | BtnColor = Color.Parse("#090909");
73 | }
74 |
75 | protected override void OnDarkThemeIsSet()
76 | {
77 | Background = Color.Parse("#202225");
78 | TextColor = Color.Parse("#FFFFFF");
79 | BtnColor = Color.Parse("#F2F2F2");
80 | }
81 |
82 | public async void DeleteCell(CodeCellViewModel cell)
83 | {
84 | if (!IsEditable) return;
85 | if (isFromAddPage)
86 | AddViewModelInstance.Cells.Remove(cell);
87 | else
88 | CodeViewModelInstance.Cells.Remove(cell);
89 | }
90 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/ViewModels/FavoritesViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.Linq;
5 | using Avalonia.Media;
6 | using CutCode.CrossPlatform.Models;
7 | using CutCode.CrossPlatform.Services;
8 | using ReactiveUI;
9 | using ReactiveUI.Fody.Helpers;
10 |
11 | namespace CutCode.CrossPlatform.ViewModels;
12 |
13 | public class FavoritesViewModel : PageBaseViewModel, IRoutableViewModel
14 | {
15 | private string _basicSort;
16 |
17 | private bool _isSearchCancelled = true;
18 | private string _languageSort;
19 |
20 | private string _searchText;
21 |
22 | public FavoritesViewModel()
23 | {
24 | Inititalise();
25 | }
26 |
27 | public FavoritesViewModel(IScreen screen)
28 | {
29 | HostScreen = screen;
30 | Inititalise();
31 | }
32 |
33 | public void Inititalise()
34 | {
35 | AllFavouriteCodes = new ObservableCollection();
36 | CodeModeToViewModel(DataBase.FavCodes);
37 |
38 | DatabaseService.Current.FavCodesUpdated += FavCodesUpdated;
39 |
40 | IsSearchBusy = false;
41 |
42 | Languages = new ObservableCollection
43 | {
44 | "All languages", "Python", "C++", "C#", "CSS", "Dart", "Golang", "Html", "Java",
45 | "Javascript", "Kotlin", "Php", "C", "Ruby", "Rust", "Sql", "Swift"
46 | };
47 | Sorts = new ObservableCollection { "Date", "Alphabet" };
48 |
49 | Sortby = DataBase.sortBy == "Date" ? 0 : 1;
50 | _basicSort = DataBase.sortBy;
51 | _languageSort = "All languages";
52 |
53 | VisChange();
54 | }
55 |
56 | [Reactive] public ObservableCollection AllFavouriteCodes { get; set; }
57 | public IList Languages { get; set; }
58 | public IList Sorts { get; set; }
59 |
60 | [Reactive] public bool EmptyLabelVisibility { get; set; }
61 |
62 | private int Sortby { get; set; }
63 |
64 | [Reactive] public string EmptyLabel { get; set; }
65 |
66 | [Reactive] public bool IsSearchBusy { get; set; }
67 |
68 | protected override void OnLightThemeIsSet()
69 | {
70 | BackgroundColor = Color.Parse("#FCFCFC");
71 | SearchBarBackground = Color.Parse("#ECECEC");
72 | SearchBarOnHoverColor = Color.Parse("#E2E2E2");
73 | SearchBarTextColor = Color.Parse("#000000");
74 | ComboboxHoverColor = Color.Parse("#C5C7C9");
75 | ComboboxBackgroundColor = Color.Parse("#E3E5E8");
76 | }
77 |
78 | protected override void OnDarkThemeIsSet()
79 | {
80 | BackgroundColor = Color.Parse("#36393F");
81 | SearchBarBackground = Color.Parse("#2A2E33");
82 | SearchBarOnHoverColor = Color.Parse("#24272B");
83 | SearchBarTextColor = Color.Parse("#FFFFFF");
84 | ComboboxHoverColor = Color.Parse("#202326");
85 | ComboboxBackgroundColor = Color.Parse("#202225");
86 | }
87 |
88 | private void FavCodesUpdated(object sender, EventArgs e)
89 | {
90 | CodeModeToViewModel(DataBase.FavCodes);
91 | SearchCancelled();
92 | }
93 |
94 | private void CodeModeToViewModel(List codes)
95 | {
96 | AllFavouriteCodes.Clear();
97 | foreach (CodeModel code in codes) AllFavouriteCodes.Add(new CodeCardViewModel(code));
98 | }
99 |
100 | private void VisChange(string text = "You don't have any notes :(")
101 | {
102 | EmptyLabelVisibility = AllFavouriteCodes.Count == 0;
103 | EmptyLabel = text;
104 | }
105 |
106 | public async void ComboBoxCommand(string sort)
107 | {
108 | var favcodes = AllFavouriteCodes.Select(c => c.Code).ToList();
109 | if (sort is "Date" or "Alphabet")
110 | {
111 | _basicSort = sort;
112 | CodeModeToViewModel(await DataBase.OrderCode(_basicSort, favcodes, "Favourite"));
113 | }
114 | else
115 | {
116 | _languageSort = sort;
117 | if (_isSearchCancelled)
118 | {
119 | var codes = await DataBase.OrderCode(_languageSort, DataBase.AllCodes);
120 | CodeModeToViewModel(await DataBase.OrderCode(_basicSort, codes, "Favourite"));
121 | }
122 | else
123 | {
124 | var codes = await DataBase.SearchCode(_searchText, "Favourite");
125 | codes = await DataBase.OrderCode(_languageSort, codes);
126 | CodeModeToViewModel(await DataBase.OrderCode(_basicSort, codes, "Favourite"));
127 | }
128 | }
129 |
130 | VisChange("Not found :(");
131 | }
132 |
133 | public async void SearchCommand(string text)
134 | {
135 | _searchText = text;
136 | _isSearchCancelled = false;
137 | if (string.IsNullOrEmpty(text)) return;
138 | IsSearchBusy = true;
139 | if (text != "" && AllFavouriteCodes.Count > 0)
140 | {
141 | CodeModeToViewModel(await DataBase.SearchCode(text, "Favourite"));
142 | VisChange("Not found :(");
143 | }
144 |
145 | IsSearchBusy = false;
146 | }
147 |
148 | public async void SearchCancelled()
149 | {
150 | var allCodes = AllFavouriteCodes.Select(c => c.Code).ToList();
151 | allCodes = await DataBase.OrderCode(_languageSort, allCodes, "Favourite");
152 | CodeModeToViewModel(allCodes);
153 | VisChange();
154 | _isSearchCancelled = true;
155 | }
156 |
157 | #region Color
158 |
159 | [Reactive] public Color BackgroundColor { get; set; }
160 |
161 | [Reactive] public Color SearchBarBackground { get; set; }
162 |
163 | [Reactive] public Color SearchBarOnHoverColor { get; set; }
164 |
165 | [Reactive] public Color SearchBarTextColor { get; set; }
166 |
167 | [Reactive] public Color ComboboxHoverColor { get; set; }
168 |
169 | [Reactive] public Color ComboboxBackgroundColor { get; set; }
170 |
171 | #endregion
172 |
173 | public string? UrlPathSegment => Guid.NewGuid().ToString().Substring(0, 5);
174 | public IScreen HostScreen { get; }
175 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/ViewModels/HomeViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.Linq;
5 | using Avalonia.Media;
6 | using CutCode.CrossPlatform.Models;
7 | using CutCode.CrossPlatform.Services;
8 | using ReactiveUI;
9 | using ReactiveUI.Fody.Helpers;
10 |
11 | namespace CutCode.CrossPlatform.ViewModels;
12 |
13 | public class HomeViewModel : PageBaseViewModel, IRoutableViewModel
14 | {
15 | private string _basicSort;
16 |
17 | private bool _isSearchCancelled = true;
18 | private string _languageSort;
19 |
20 | private string _searchText;
21 |
22 | public HomeViewModel()
23 | {
24 | Initialise();
25 | }
26 |
27 | public HomeViewModel(IScreen screen)
28 | {
29 | HostScreen = screen;
30 | Initialise();
31 | }
32 |
33 | public void Initialise()
34 | {
35 | AllCodes = new ObservableCollection();
36 | CodeModeToViewModel(DataBase.AllCodes);
37 |
38 | DatabaseService.Current.AllCodesUpdated += AllCodesUpdated;
39 |
40 | IsSearchBusy = false;
41 |
42 | Languages = new ObservableCollection
43 | {
44 | "All languages", "Python", "C++", "C#", "CSS", "Dart", "Golang", "Html", "Java",
45 | "Javascript", "Kotlin", "Php", "C", "Ruby", "Rust", "Sql", "Swift"
46 | };
47 | Sorts = new ObservableCollection { "Date", "Alphabet" };
48 |
49 | Sortby = DataBase.sortBy == "Date" ? 0 : 1;
50 | _basicSort = DataBase.sortBy;
51 | _languageSort = "All languages";
52 |
53 | VisChange();
54 | }
55 |
56 | [Reactive] public ObservableCollection AllCodes { get; set; }
57 | public IList Languages { get; set; }
58 | public IList Sorts { get; set; }
59 |
60 | [Reactive] public bool EmptyLabelVisibility { get; set; }
61 |
62 | private int Sortby { get; set; }
63 |
64 | [Reactive] public string EmptyLabel { get; set; }
65 |
66 | [Reactive] public bool IsSearchBusy { get; set; }
67 |
68 | protected override void OnLightThemeIsSet()
69 | {
70 | BackgroundColor = Color.Parse("#FCFCFC");
71 | SearchBarBackground = Color.Parse("#ECECEC");
72 | SearchBarOnHoverColor = Color.Parse("#E2E2E2");
73 | SearchBarTextColor = Color.Parse("#000000");
74 | ComboboxHoverColor = Color.Parse("#C5C7C9");
75 | ComboboxBackgroundColor = Color.Parse("#E3E5E8");
76 | }
77 |
78 | protected override void OnDarkThemeIsSet()
79 | {
80 | BackgroundColor = Color.Parse("#36393F");
81 | SearchBarBackground = Color.Parse("#2A2E33");
82 | SearchBarOnHoverColor = Color.Parse("#24272B");
83 | SearchBarTextColor = Color.Parse("#FFFFFF");
84 | ComboboxHoverColor = Color.Parse("#202326");
85 | ComboboxBackgroundColor = Color.Parse("#202225");
86 | }
87 |
88 | private void AllCodesUpdated(object sender, EventArgs e)
89 | {
90 | SearchCancelled();
91 | }
92 |
93 | private void CodeModeToViewModel(List codes)
94 | {
95 | var tempCodes = new ObservableCollection();
96 | foreach (CodeModel code in codes) tempCodes.Add(new CodeCardViewModel(code));
97 | AllCodes = tempCodes;
98 | }
99 |
100 | private void VisChange(string text = "You don't have any notes :(")
101 | {
102 | EmptyLabelVisibility = AllCodes.Count == 0;
103 | EmptyLabel = text;
104 | }
105 |
106 | public async void ComboBoxCommand(string sort)
107 | {
108 | var allcodes = AllCodes.Select(c => c.Code).ToList();
109 | if (sort is "Date" or "Alphabet")
110 | {
111 | _basicSort = sort;
112 | CodeModeToViewModel(await DataBase.OrderCode(_basicSort, allcodes));
113 | }
114 | else
115 | {
116 | _languageSort = sort;
117 | if (_isSearchCancelled)
118 | {
119 | var codes = await DataBase.OrderCode(_languageSort, DataBase.AllCodes);
120 | CodeModeToViewModel(await DataBase.OrderCode(_basicSort, codes));
121 | }
122 | else
123 | {
124 | var codes = await DataBase.SearchCode(_searchText, "Home");
125 | codes = await DataBase.OrderCode(_languageSort, codes);
126 | CodeModeToViewModel(await DataBase.OrderCode(_basicSort, codes));
127 | }
128 | }
129 |
130 | VisChange("Not found :(");
131 | }
132 |
133 | public async void SearchCommand(string text)
134 | {
135 | _searchText = text;
136 | _isSearchCancelled = false;
137 | if (string.IsNullOrEmpty(text)) return;
138 | IsSearchBusy = true;
139 | if (text != "" && AllCodes.Count > 0)
140 | {
141 | CodeModeToViewModel(await DataBase.SearchCode(text, "Home"));
142 | VisChange("Not found :(");
143 | }
144 |
145 | IsSearchBusy = false;
146 | }
147 |
148 | public async void SearchCancelled()
149 | {
150 | var codes = await DataBase.OrderCode(_languageSort, AllCodes.Select(c => c.Code).ToList());
151 | CodeModeToViewModel(await DataBase.OrderCode(_basicSort, codes));
152 | VisChange();
153 | _isSearchCancelled = true;
154 | }
155 |
156 | #region Color
157 |
158 | [Reactive] public Color BackgroundColor { get; set; }
159 |
160 | [Reactive] public Color SearchBarBackground { get; set; }
161 |
162 | [Reactive] public Color SearchBarOnHoverColor { get; set; }
163 |
164 | [Reactive] public Color SearchBarTextColor { get; set; }
165 |
166 | [Reactive] public Color ComboboxHoverColor { get; set; }
167 |
168 | [Reactive] public Color ComboboxBackgroundColor { get; set; }
169 |
170 | #endregion
171 |
172 | public string? UrlPathSegment => Guid.NewGuid().ToString().Substring(0, 5);
173 | public IScreen HostScreen { get; }
174 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/ViewModels/MainWindowViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.Reactive;
5 | using Avalonia.Media;
6 | using Avalonia.Threading;
7 | using CutCode.CrossPlatform.Helpers;
8 | using CutCode.CrossPlatform.Models;
9 | using CutCode.CrossPlatform.Services;
10 | using CutCode.CrossPlatform.Views;
11 | using ReactiveUI;
12 | using ReactiveUI.Fody.Helpers;
13 | using Notification = CutCode.CrossPlatform.Models.Notification;
14 |
15 | namespace CutCode.CrossPlatform.ViewModels;
16 |
17 | public class MainWindowViewModel : PageBaseViewModel, IScreen
18 | {
19 | public MainWindowViewModel()
20 | {
21 | Router = new RoutingState();
22 | Router.Navigate.Execute(new HomeViewModel(this));
23 |
24 | GoHome = ReactiveCommand.CreateFromObservable(() => Router.Navigate.Execute(new HomeViewModel(this)));
25 | GoAdd = ReactiveCommand.CreateFromObservable(() => Router.Navigate.Execute(new AddViewModel(this)));
26 | GoFavourites =
27 | ReactiveCommand.CreateFromObservable(() => Router.Navigate.Execute(new FavoritesViewModel(this)));
28 | GoSettings = ReactiveCommand.CreateFromObservable(() => Router.Navigate.Execute(new SettingsViewModel(this)));
29 |
30 | Router.CurrentViewModel.Subscribe(x =>
31 | OnNaviagted(x?.GetType().Name)
32 | );
33 |
34 | GlobalEvents.OnShowCodeModel += GlobalEventsOnOnShowCodeModel;
35 | GlobalEvents.OnCancelClicked += GlobalEventsOnOnCancelClicked;
36 | }
37 |
38 | private void GlobalEventsOnOnCancelClicked(object? sender, EventArgs e)
39 | {
40 | Router.Navigate.Execute(new HomeViewModel(this));
41 | }
42 |
43 | private void GlobalEventsOnOnShowCodeModel(object? sender, CodeModel e)
44 | {
45 | Router.Navigate.Execute(new CodeViewModel(e, this));
46 | }
47 |
48 | [Reactive] public bool IsDarkTheme { get; set; }
49 |
50 | public RoutingState Router { get; }
51 |
52 | public event EventHandler Navigated;
53 |
54 | private void OnNaviagted(string? vm)
55 | {
56 | Navigated?.Invoke(this, vm);
57 | }
58 |
59 | protected override void OnLoad()
60 | {
61 | IsDarkTheme = ThemeService.Current.Theme == ThemeType.Dark;
62 |
63 | this.WhenAnyValue(x => x.IsDarkTheme)
64 | .Subscribe(x => { ThemeService.Current.Theme = IsDarkTheme ? ThemeType.Dark : ThemeType.Light; });
65 |
66 |
67 | NotificationService.ShowNotification += ShowNotification!;
68 | NotificationService.OnCloseNotification += ExitNotification!;
69 | Notifications = new ObservableCollection();
70 | }
71 |
72 | protected override void OnLightThemeIsSet()
73 | {
74 | WindowsBtnColor = Color.Parse("#090909");
75 | BackgroundColor = Color.Parse("#FCFCFC");
76 | TitleBarColor = Color.Parse("#E3E5E8");
77 | SideBarColor = Color.Parse("#F2F3F5");
78 | MainTextColor = Color.Parse("#0B0B13");
79 |
80 | TitlebarBtnsHoverColor = Color.Parse("#D0D1D2");
81 | MenuButtonColour = Color.Parse("#0B0B13");
82 | }
83 |
84 | protected override void OnDarkThemeIsSet()
85 | {
86 | WindowsBtnColor = Color.Parse("#F2F2F2");
87 | BackgroundColor = Color.Parse("#36393F");
88 | TitleBarColor = Color.Parse("#202225");
89 | SideBarColor = Color.Parse("#32363C");
90 | MainTextColor = Color.Parse("#94969A");
91 |
92 | TitlebarBtnsHoverColor = Color.Parse("#373737");
93 | MenuButtonColour = Color.Parse("#94969A");
94 | }
95 |
96 | #region Color
97 |
98 | [Reactive] public Color WindowsBtnColor { get; set; }
99 |
100 | [Reactive] public Color BackgroundColor { get; set; }
101 |
102 | [Reactive] public Color TitleBarColor { get; set; }
103 |
104 | [Reactive] public Color SideBarColor { get; set; }
105 |
106 | [Reactive] public Color MainTextColor { get; set; }
107 |
108 | [Reactive] public Color TitlebarBtnsHoverColor { get; set; }
109 |
110 | [Reactive] public Color MenuButtonColour { get; set; }
111 |
112 | #endregion
113 |
114 | #region Commands
115 |
116 | public ReactiveCommand GoHome { get; }
117 | public ReactiveCommand GoAdd { get; }
118 | public ReactiveCommand GoFavourites { get; }
119 | public ReactiveCommand GoSettings { get; }
120 |
121 | #endregion
122 |
123 | #region NotificationDialogView
124 |
125 | [Reactive] public ObservableCollection Notifications { get; set; }
126 |
127 | private readonly List WaitingNotifications = new();
128 | private readonly List liveNotifications = new();
129 |
130 | private void ShowNotification(object sender, EventArgs e)
131 | {
132 | Notification? notification = sender as Notification;
133 |
134 | NotificationView notifcationView = new()
135 | {
136 | DataContext = new NotificationViewModel(notification!)
137 | };
138 | notification.View = notifcationView;
139 |
140 | if (Notifications.Count > 2)
141 | {
142 | WaitingNotifications.Add(notification);
143 | }
144 | else
145 | {
146 | Notifications.Add(notification);
147 |
148 | DispatcherTimer closeTimer = new()
149 | {
150 | Interval = TimeSpan.FromSeconds(notification.Delay),
151 | IsEnabled = true
152 | };
153 | liveNotifications.Add(new LiveNotification { Timer = closeTimer, Notification = notification });
154 | closeTimer.Tick += CloseNotification!;
155 | }
156 | }
157 |
158 | private void ExitNotification(object sender, EventArgs e)
159 | {
160 | Notification? notification = sender as Notification;
161 | LiveNotification newLiveNotification = new();
162 | foreach (LiveNotification liveNotification in liveNotifications)
163 | if (liveNotification.Notification == notification)
164 | {
165 | newLiveNotification = liveNotification;
166 | break;
167 | }
168 |
169 | Notifications.Remove(notification);
170 | UpdateNotification();
171 | newLiveNotification.Timer.Stop();
172 | liveNotifications.Remove(newLiveNotification);
173 | }
174 |
175 | private void CloseNotification(object sender, EventArgs e)
176 | {
177 | DispatcherTimer? timer = sender as DispatcherTimer;
178 | LiveNotification liveNotification = new();
179 | foreach (LiveNotification _liveNotification in liveNotifications)
180 | if (_liveNotification.Timer == timer)
181 | {
182 | liveNotification = _liveNotification;
183 | break;
184 | }
185 |
186 | Notifications.Remove(liveNotification.Notification);
187 | liveNotifications.Remove(liveNotification);
188 | UpdateNotification();
189 | timer.Stop();
190 | }
191 |
192 | private void UpdateNotification()
193 | {
194 | if (WaitingNotifications.Count > 0)
195 | for (int i = 0; i < 3 - Notifications.Count; i++)
196 | {
197 | if (WaitingNotifications.Count == 0) break;
198 |
199 | Notification notification = WaitingNotifications[i];
200 | WaitingNotifications.RemoveAt(i);
201 | NotificationService.CreateNotification(notification.NotificationType, notification.Message,
202 | notification.Delay);
203 | }
204 | }
205 |
206 | #endregion
207 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/ViewModels/NotificationViewModel.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Media;
2 | using CutCode.CrossPlatform.Models;
3 | using ReactiveUI.Fody.Helpers;
4 |
5 | namespace CutCode.CrossPlatform.ViewModels;
6 |
7 | public class NotificationViewModel : PageBaseViewModel
8 | {
9 | private readonly Notification Notification;
10 |
11 | public NotificationViewModel(Notification notification)
12 | {
13 | Notification = notification;
14 | NotificationType = Notification.NotificationType;
15 | Message = Notification.Message;
16 | }
17 |
18 | [Reactive] public Color Background { get; set; }
19 |
20 | [Reactive] public Color TextColor { get; set; }
21 |
22 | [Reactive] public string NotificationType { get; set; }
23 |
24 | [Reactive] public string Message { get; set; }
25 |
26 | protected override void OnLightThemeIsSet()
27 | {
28 | Background = Color.Parse("#F2F3F5");
29 | TextColor = Color.Parse("#0B0B13");
30 | }
31 |
32 | protected override void OnDarkThemeIsSet()
33 | {
34 | Background = Color.Parse("#2F3136");
35 | TextColor = Color.Parse("#CED0D4");
36 | }
37 |
38 | public void CloseNotification()
39 | {
40 | NotificationService.CloseNotification(Notification);
41 | }
42 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/ViewModels/PageBaseViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Avalonia;
3 | using Avalonia.Markup.Xaml.Styling;
4 | using Avalonia.Media;
5 | using Avalonia.Platform;
6 | using Avalonia.Themes.Fluent;
7 | using CutCode.CrossPlatform.Services;
8 | using ReactiveUI;
9 | using PageService = CutCode.CrossPlatform.Services.PageService;
10 | using ThemeService = CutCode.CrossPlatform.Services.ThemeService;
11 |
12 | namespace CutCode.CrossPlatform.ViewModels
13 | {
14 | public class PageBaseViewModel : ViewModelBase
15 | {
16 | public PageBaseViewModel()
17 | {
18 | ThemeService = ThemeService.Current;
19 | DataBase = DatabaseService.Current;
20 | PageService = PageService.Current;
21 | AssetLoader = AvaloniaLocator.CurrentMutable.GetService();
22 | NotificationService = NotificationService.Current;
23 |
24 | ThemeService.ThemeChanged += (s, e) =>
25 | {
26 | OnThemeChanged();
27 | };
28 | OnLoad();
29 | OnThemeChanged();
30 | }
31 |
32 | protected virtual void OnLoad()
33 | {
34 |
35 | }
36 |
37 | protected virtual void OnThemeChanged()
38 | {
39 | if (ThemeService.Theme == ThemeType.Light)
40 | {
41 | OnLightThemeIsSet();
42 | }
43 | else
44 | {
45 | OnDarkThemeIsSet();
46 | }
47 | }
48 |
49 | protected virtual void OnLightThemeIsSet()
50 | {
51 |
52 | }
53 |
54 | protected virtual void OnDarkThemeIsSet()
55 | {
56 |
57 | }
58 |
59 | protected IAssetLoader? AssetLoader
60 | {
61 | get;
62 | set;
63 | }
64 |
65 | public ThemeService ThemeService
66 | {
67 | get;
68 | set;
69 | }
70 |
71 | protected DatabaseService DataBase
72 | {
73 | get;
74 | set;
75 | }
76 |
77 | protected PageService PageService
78 | {
79 | get;
80 | set;
81 | }
82 |
83 | protected NotificationService NotificationService
84 | {
85 | get;
86 | set;
87 | }
88 | }
89 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/ViewModels/SettingsViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using Avalonia;
5 | using Avalonia.Controls;
6 | using Avalonia.Controls.ApplicationLifetimes;
7 | using Avalonia.Media;
8 | using CutCode.CrossPlatform.Models;
9 | using ReactiveUI;
10 | using ReactiveUI.Fody.Helpers;
11 |
12 | namespace CutCode.CrossPlatform.ViewModels;
13 |
14 | public class SettingsViewModel : PageBaseViewModel, IRoutableViewModel
15 | {
16 | public SettingsViewModel(IScreen screen)
17 | {
18 | HostScreen = screen;
19 | }
20 |
21 | public SettingsViewModel()
22 | {
23 | }
24 |
25 | [Reactive] public Color BackgroundColor { get; set; }
26 |
27 | [Reactive] public Color MainTextColor { get; set; }
28 |
29 | [Reactive] public Color CardColor { get; set; }
30 |
31 | [Reactive] public Color BtnColor { get; set; }
32 |
33 | public string? UrlPathSegment => Guid.NewGuid().ToString().Substring(0, 5);
34 | public IScreen HostScreen { get; }
35 |
36 | protected override void OnLightThemeIsSet()
37 | {
38 | BackgroundColor = Color.Parse("#FCFCFC");
39 | MainTextColor = Color.Parse("#0B0B13");
40 | CardColor = Color.Parse("#F2F3F5");
41 | BtnColor = Color.Parse("#E5E6E8");
42 | }
43 |
44 | protected override void OnDarkThemeIsSet()
45 | {
46 | BackgroundColor = Color.Parse("#36393F");
47 | MainTextColor = Color.Parse("#94969A");
48 | CardColor = Color.Parse("#2F3136");
49 | BtnColor = Color.Parse("#27282C");
50 | }
51 |
52 | public async void SyncCommand(string sync)
53 | {
54 | string message = "";
55 | if (sync == "Import")
56 | {
57 | OpenFileDialog fileDialog = new();
58 | fileDialog.AllowMultiple = false;
59 | fileDialog.Directory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
60 | var fileExt = new List
61 | {
62 | new()
63 | };
64 | fileExt[0].Extensions = new List { "whl" };
65 |
66 | fileDialog.Filters = fileExt;
67 | if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktopLifetime)
68 | {
69 | string[]? dialogResult = await fileDialog.ShowAsync(desktopLifetime.MainWindow);
70 |
71 | if (!string.IsNullOrEmpty(dialogResult?[0]))
72 | {
73 | Notification processing =
74 | NotificationService.CreateNotification("Notification", "Processing...", 100);
75 | message = await DataBase.ImportData(dialogResult[0]);
76 | NotificationService.CreateNotification("Notification", message, 4);
77 | NotificationService.CloseNotification(processing);
78 | return;
79 | }
80 | }
81 | }
82 | else
83 | {
84 | SaveFileDialog fileDialog = new();
85 | fileDialog.Directory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
86 | var fileExt = new List
87 | {
88 | new()
89 | };
90 | fileExt[0].Extensions = new List { "whl" };
91 | fileDialog.InitialFileName = $"Export_CutCode_{DateTime.Now.ToString("yyyyMMddhhmmss")}.whl";
92 | fileDialog.Filters = fileExt;
93 | if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktopLifetime)
94 | {
95 | string? dialogResult = await fileDialog.ShowAsync(desktopLifetime.MainWindow);
96 | if (!string.IsNullOrEmpty(dialogResult)) message = DataBase.ExportData(dialogResult);
97 | }
98 | }
99 |
100 | if (!string.IsNullOrEmpty(message)) NotificationService.CreateNotification("Notification", message, 4);
101 | }
102 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/ViewModels/ViewModelBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using ReactiveUI;
5 |
6 | namespace CutCode.CrossPlatform.ViewModels
7 | {
8 | public class ViewModelBase : ReactiveObject
9 | {
10 | }
11 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Views/AddView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia;
2 | using Avalonia.Controls;
3 | using Avalonia.Markup.Xaml;
4 | using Avalonia.ReactiveUI;
5 | using CutCode.CrossPlatform.ViewModels;
6 |
7 | namespace CutCode.CrossPlatform.Views
8 | {
9 | public class AddView : ReactiveUserControl
10 | {
11 | public AddView()
12 | {
13 | InitializeComponent();
14 | }
15 |
16 | private void InitializeComponent()
17 | {
18 | AvaloniaXamlLoader.Load(this);
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Views/CodeCardView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia;
2 | using Avalonia.Controls;
3 | using Avalonia.Markup.Xaml;
4 |
5 | namespace CutCode.CrossPlatform.Views
6 | {
7 | public class CodeCardView : UserControl
8 | {
9 | public CodeCardView()
10 | {
11 | InitializeComponent();
12 | }
13 |
14 | private void InitializeComponent()
15 | {
16 | AvaloniaXamlLoader.Load(this);
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Views/CodeCellView.axaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
29 |
30 |
38 |
39 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
66 |
67 |
90 |
91 |
106 |
107 |
108 |
123 |
124 |
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Views/CodeCellView.axaml.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using System.Reactive.Disposables;
3 | using Avalonia;
4 | using Avalonia.Controls;
5 | using Avalonia.LogicalTree;
6 | using Avalonia.Markup.Xaml;
7 | using Avalonia.ReactiveUI;
8 | using AvaloniaEdit;
9 | using AvaloniaEdit.Document;
10 | using AvaloniaEdit.Indentation.CSharp;
11 | using AvaloniaEdit.TextMate;
12 | using AvaloniaEdit.TextMate.Grammars;
13 | using CutCode.CrossPlatform.Helpers;
14 | using CutCode.CrossPlatform.Services;
15 | using CutCode.CrossPlatform.ViewModels;
16 | using ReactiveUI;
17 | using TextMateSharp.Internal.Themes;
18 |
19 | namespace CutCode.CrossPlatform.Views
20 | {
21 | public class CodeCellView : ReactiveUserControl
22 | {
23 | private TextEditor TextEditor => this.FindControl(nameof(TextEditor));
24 | private TextMate.Installation _textMateInstallation;
25 | private RegistryOptions _registryOptions;
26 |
27 | public CodeCellView()
28 | {
29 | InitializeComponent();
30 | this.WhenActivated(d =>
31 | {
32 | // this.Bind(ViewModel, x => x.Code, x => x.TextEditor.Text).DisposeWith(d);
33 | this.Bind(ViewModel, x => x.Document, x => x.TextEditor.Document).DisposeWith(d);
34 | });
35 |
36 | TextEditor.TextArea.IndentationStrategy = new CSharpIndentationStrategy(TextEditor.Options);
37 |
38 | _registryOptions = new RegistryOptions(ThemeService.Current.Theme == ThemeType.Light ? ThemeName.LightPlus : ThemeName.DarkPlus);
39 | ThemeService.Current.ThemeChanged += (sender, args) =>
40 | {
41 | _registryOptions = new RegistryOptions(ThemeService.Current.Theme == ThemeType.Light ? ThemeName.LightPlus : ThemeName.DarkPlus);
42 | _textMateInstallation = TextEditor.InstallTextMate(_registryOptions);
43 |
44 | var scopeName = _registryOptions.GetScopeByLanguageId(_currentLanguage!.Id);
45 | _textMateInstallation.SetGrammar(scopeName);
46 | };
47 |
48 | _textMateInstallation = TextEditor.InstallTextMate(_registryOptions);
49 |
50 | _currentLanguage = _registryOptions.GetLanguageByExtension(".cs");
51 |
52 | var scopeName = _registryOptions.GetScopeByLanguageId(_currentLanguage.Id);
53 | _textMateInstallation.SetGrammar(scopeName);
54 | GlobalEvents.OnLanguageSet += GlobalEventsOnOnLanguageSet;
55 | GlobalEvents.ViewRegistered(this);
56 | }
57 |
58 | private Language _currentLanguage;
59 | private void GlobalEventsOnOnLanguageSet(object? sender, Language e)
60 | {
61 | _currentLanguage = e;
62 | string scopeName = _registryOptions.GetScopeByLanguageId(e.Id);
63 | _textMateInstallation.SetGrammar(scopeName);
64 | }
65 |
66 | private void InitializeComponent()
67 | {
68 | AvaloniaXamlLoader.Load(this);
69 | }
70 | }
71 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Views/CodeView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia;
2 | using Avalonia.Controls;
3 | using Avalonia.Markup.Xaml;
4 | using Avalonia.ReactiveUI;
5 | using CutCode.CrossPlatform.ViewModels;
6 |
7 | namespace CutCode.CrossPlatform.Views
8 | {
9 | public class CodeView : ReactiveUserControl
10 | {
11 | public CodeView()
12 | {
13 | InitializeComponent();
14 | }
15 |
16 | private void InitializeComponent()
17 | {
18 | AvaloniaXamlLoader.Load(this);
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Views/FavoritesView.axaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
32 |
33 |
34 |
41 |
42 |
49 |
50 |
51 |
52 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Views/FavoritesView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia;
2 | using Avalonia.Controls;
3 | using Avalonia.Markup.Xaml;
4 | using Avalonia.ReactiveUI;
5 | using CutCode.CrossPlatform.ViewModels;
6 |
7 | namespace CutCode.CrossPlatform.Views
8 | {
9 | public class FavoritesView : ReactiveUserControl
10 | {
11 | public FavoritesView()
12 | {
13 | InitializeComponent();
14 | }
15 |
16 | private void InitializeComponent()
17 | {
18 | AvaloniaXamlLoader.Load(this);
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Views/HomeView.axaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
32 |
33 |
34 |
41 |
42 |
49 |
50 |
51 |
52 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
71 |
72 |
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Views/HomeView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia;
2 | using Avalonia.Controls;
3 | using Avalonia.Markup.Xaml;
4 | using Avalonia.ReactiveUI;
5 | using CutCode.CrossPlatform.ViewModels;
6 | using ReactiveUI;
7 |
8 | namespace CutCode.CrossPlatform.Views
9 | {
10 | public partial class HomeView : ReactiveUserControl
11 | {
12 | public HomeView()
13 | {
14 | InitializeComponent();
15 | this.WhenActivated(d => { });
16 | }
17 |
18 | private void InitializeComponent()
19 | {
20 | AvaloniaXamlLoader.Load(this);
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Views/MainWindow.axaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Reactive.Linq;
4 | using System.Threading.Tasks;
5 | using Avalonia;
6 | using Avalonia.Controls;
7 | using Avalonia.Controls.Mixins;
8 | using Avalonia.Input;
9 | using Avalonia.Interactivity;
10 | using Avalonia.LogicalTree;
11 | using Avalonia.Markup.Xaml;
12 | using Avalonia.ReactiveUI;
13 | using Avalonia.Threading;
14 | using Avalonia.VisualTree;
15 | using CutCode.CrossPlatform.Controls;
16 | using CutCode.CrossPlatform.Helpers;
17 | using CutCode.CrossPlatform.ViewModels;
18 | using ReactiveUI;
19 |
20 | namespace CutCode.CrossPlatform.Views
21 | {
22 | public partial class MainWindow : ReactiveWindow
23 | {
24 | public StackPanel MenuPanel => this.FindControl(nameof(MenuPanel));
25 |
26 | public MainWindow()
27 | {
28 | InitializeComponent();
29 | #if DEBUG
30 | this.AttachDevTools();
31 | #endif
32 | this.WhenActivated(d =>
33 | {
34 | if (ViewModel != null) ViewModel.Navigated += ViewModelOnNavigated;
35 | });
36 | }
37 |
38 | private void ViewModelOnNavigated(object? sender, string? e)
39 | {
40 | var lt = MenuPanel.GetLogicalChildren();
41 | foreach (NavigationItem? logical in lt.Cast())
42 | {
43 | logical.IsActive = logical.Name == e;
44 | }
45 | }
46 |
47 | public void ChangeWindowPosition(object sender, PointerPressedEventArgs e)
48 | {
49 | BeginMoveDrag(e);
50 | }
51 |
52 | private void InitializeComponent()
53 | {
54 | AvaloniaXamlLoader.Load(this);
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Views/NotificationView.axaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
19 |
23 |
24 |
25 |
27 |
28 |
29 |
30 |
34 |
47 |
48 |
49 |
50 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Views/NotificationView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia;
2 | using Avalonia.Controls;
3 | using Avalonia.Markup.Xaml;
4 |
5 | namespace CutCode.CrossPlatform.Views
6 | {
7 | public class NotificationView : UserControl
8 | {
9 | public NotificationView()
10 | {
11 | InitializeComponent();
12 | }
13 |
14 | private void InitializeComponent()
15 | {
16 | AvaloniaXamlLoader.Load(this);
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Views/SettingsView.axaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
34 |
35 |
39 |
40 |
44 |
61 |
62 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/Views/SettingsView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia;
2 | using Avalonia.Controls;
3 | using Avalonia.Markup.Xaml;
4 | using Avalonia.ReactiveUI;
5 | using CutCode.CrossPlatform.ViewModels;
6 |
7 | namespace CutCode.CrossPlatform.Views
8 | {
9 | public class SettingsView : ReactiveUserControl
10 | {
11 | public SettingsView()
12 | {
13 | InitializeComponent();
14 | }
15 |
16 | private void InitializeComponent()
17 | {
18 | AvaloniaXamlLoader.Load(this);
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "5.0",
4 | "rollForward": "latestMajor",
5 | "allowPrerelease": true
6 | }
7 | }
--------------------------------------------------------------------------------
/src/CutCode.CrossPlatform/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/CutCode.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.31515.178
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CutCode.CrossPlatform", "CutCode.CrossPlatform\CutCode.CrossPlatform.csproj", "{E09743C5-B298-4EA1-9E47-EDF36087C1D4}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Debug|iPhone = Debug|iPhone
12 | Debug|iPhoneSimulator = Debug|iPhoneSimulator
13 | Release|Any CPU = Release|Any CPU
14 | Release|iPhone = Release|iPhone
15 | Release|iPhoneSimulator = Release|iPhoneSimulator
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {E09743C5-B298-4EA1-9E47-EDF36087C1D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {E09743C5-B298-4EA1-9E47-EDF36087C1D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {E09743C5-B298-4EA1-9E47-EDF36087C1D4}.Debug|iPhone.ActiveCfg = Debug|Any CPU
21 | {E09743C5-B298-4EA1-9E47-EDF36087C1D4}.Debug|iPhone.Build.0 = Debug|Any CPU
22 | {E09743C5-B298-4EA1-9E47-EDF36087C1D4}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
23 | {E09743C5-B298-4EA1-9E47-EDF36087C1D4}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
24 | {E09743C5-B298-4EA1-9E47-EDF36087C1D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {E09743C5-B298-4EA1-9E47-EDF36087C1D4}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {E09743C5-B298-4EA1-9E47-EDF36087C1D4}.Release|iPhone.ActiveCfg = Release|Any CPU
27 | {E09743C5-B298-4EA1-9E47-EDF36087C1D4}.Release|iPhone.Build.0 = Release|Any CPU
28 | {E09743C5-B298-4EA1-9E47-EDF36087C1D4}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
29 | {E09743C5-B298-4EA1-9E47-EDF36087C1D4}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | GlobalSection(ExtensibilityGlobals) = postSolution
35 | SolutionGuid = {905EA586-A15E-43D6-BB93-BD17F4E9C307}
36 | EndGlobalSection
37 | EndGlobal
38 |
--------------------------------------------------------------------------------
/src/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "5.0",
4 | "rollForward": "latestMajor",
5 | "allowPrerelease": true
6 | }
7 | }
--------------------------------------------------------------------------------
/src/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------