mirror of
https://github.com/gwdevhub/Daybreak.git
synced 2026-09-16 05:19:23 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f218b89f6c | ||
|
|
cc607b37c9 | ||
|
|
f80ea8cf0c | ||
|
|
39f6707d23 | ||
|
|
eb11029ece | ||
|
|
4583b5b2d3 | ||
|
|
8c01377667 | ||
|
|
9a130d71dd | ||
|
|
018ed6c5b5 | ||
|
|
cb48248c82 | ||
|
|
e1284375e2 | ||
|
|
d38d620a84 | ||
|
|
ce810dafab | ||
|
|
aabc98e4fc | ||
|
|
7eb0b7cc4f | ||
|
|
f1eb829ac4 | ||
|
|
4b03a5a16f | ||
|
|
71c90100be | ||
|
|
ee512d130d | ||
|
|
03d0759e57 | ||
|
|
0db7628d66 | ||
|
|
d1d1ba6c08 | ||
|
|
d16a88a9bc | ||
|
|
a9d93f4162 | ||
|
|
632b5a55ac | ||
|
|
6424505631 | ||
|
|
dfc1d3ba0a | ||
|
|
5bee88016d | ||
|
|
5a37250680 | ||
|
|
1c4ccb9fa3 | ||
|
|
8403dadca7 | ||
|
|
4ac4cb0886 | ||
|
|
74f13d2447 | ||
|
|
bf53793729 | ||
|
|
e69dbf6791 | ||
|
|
a0eafa8a13 | ||
|
|
b0a236beb4 | ||
|
|
c10b81f3a1 | ||
|
|
6cd51d6584 | ||
|
|
a283117cc8 | ||
|
|
329e64232c | ||
|
|
feb3c9042e | ||
|
|
71f15f56a4 | ||
|
|
d37951b832 | ||
|
|
908a149df4 | ||
|
|
38cf140dfa | ||
|
|
d13e1a2d08 | ||
|
|
a0c7842b84 | ||
|
|
de13b68633 | ||
|
|
f289602068 | ||
|
|
15f4ee8979 | ||
|
|
d826dea457 | ||
|
|
b89a6666a3 | ||
|
|
1dc69fd0c2 | ||
|
|
5005b07f09 | ||
|
|
0b692165e0 | ||
|
|
ffee0fdf4c | ||
|
|
72b4cd5470 | ||
|
|
dc9be53ace | ||
|
|
3a8a6b0f7f | ||
|
|
7cdd0534f6 | ||
|
|
4b14ab9312 | ||
|
|
57e1ddb8da | ||
|
|
c7609c0f7e | ||
|
|
1eca8021d2 | ||
|
|
0077f35c4d | ||
|
|
28b0a0a138 | ||
|
|
cc7ce92013 | ||
|
|
5bd02e56ee | ||
|
|
8c7cd0a562 | ||
|
|
3ab3f72366 | ||
|
|
733883a6c2 | ||
|
|
d1ed8aeaf6 | ||
|
|
66ad44b8ce | ||
|
|
18e51ae408 | ||
|
|
06940dbf38 | ||
|
|
875b29f8ba | ||
|
|
a953c3a0d3 | ||
|
|
ce198fcfc9 | ||
|
|
3d84648af2 | ||
|
|
38bb43bba3 | ||
|
|
cc00709016 | ||
|
|
ee02b3b49a | ||
|
|
d1d6b7d757 | ||
|
|
4e1c0c4f50 | ||
|
|
2a7e2c90fc | ||
|
|
0dc957a99d | ||
|
|
f3f0aeb97e | ||
|
|
d6dbe6f2cd | ||
|
|
79da1801bc | ||
|
|
2b692b2d88 | ||
|
|
a7a98f7288 | ||
|
|
5d27d9c380 | ||
|
|
fb4185b541 | ||
|
|
d2d6e87e12 | ||
|
|
354cdda109 | ||
|
|
83429e264a | ||
|
|
ffdf374cdd | ||
|
|
aed34608ee | ||
|
|
18981e131d | ||
|
|
fe0a77d89d | ||
|
|
dbfd555f0d | ||
|
|
85d4ac3a29 | ||
|
|
dcb983d3de | ||
|
|
ba1e4348ad | ||
|
|
04bc7cffc6 | ||
|
|
01b74a936b | ||
|
|
654b6bc10f | ||
|
|
c9e6b9f626 | ||
|
|
554f1aea9b | ||
|
|
6fb817855c | ||
|
|
b3f5fadfe3 | ||
|
|
9275b7a7f8 | ||
|
|
2d06ff85b8 | ||
|
|
07d06313d9 | ||
|
|
546409130c | ||
|
|
82436872f8 | ||
|
|
ad6f76af0c | ||
|
|
8f0ad91a22 | ||
|
|
6a70c5b7cc | ||
|
|
5f5d67fdf2 | ||
|
|
150b41647a | ||
|
|
66e52e7324 | ||
|
|
23328240a9 | ||
|
|
3f06e9486d | ||
|
|
52a8e912e9 | ||
|
|
641aa8250e | ||
|
|
faa47f32c7 | ||
|
|
e3dac780df | ||
|
|
dfc0f12150 | ||
|
|
638fb38fa0 | ||
|
|
4d6a06ccdf | ||
|
|
3228604876 | ||
|
|
44879924d6 | ||
|
|
6b7478f6ae | ||
|
|
f54d95c1e7 | ||
|
|
5315a45a98 | ||
|
|
8575d970a3 | ||
|
|
5c611eca4f | ||
|
|
71aa37b965 | ||
|
|
0f1b1cc83d | ||
|
|
198c1e6eb3 | ||
|
|
e7c9111a1f | ||
|
|
1191e996db | ||
|
|
19de3c99f9 | ||
|
|
d857b6dc26 | ||
|
|
68b5b79035 | ||
|
|
318032d998 | ||
|
|
483860532f | ||
|
|
694dbe82a9 | ||
|
|
a936f24e32 | ||
|
|
a2ec87ced2 | ||
|
|
48955a7dd7 | ||
|
|
9d7c6c29b0 | ||
|
|
902d210dfd | ||
|
|
57867851a9 | ||
|
|
ca82cc92bf | ||
|
|
569ce1e656 | ||
|
|
a96c6c3f66 | ||
|
|
28c3b2f8c1 | ||
|
|
deeccd81b4 | ||
|
|
6a27245ae8 | ||
|
|
6f4063abb7 | ||
|
|
f307bcd665 | ||
|
|
02ca41ba6d | ||
|
|
a0ebc87b7c | ||
|
|
d21c55deb0 | ||
|
|
50a8131ec2 | ||
|
|
e70cfa3d99 | ||
|
|
4c0c45f1c7 | ||
|
|
a9e819a83a | ||
|
|
65830f9125 | ||
|
|
3d9106addf | ||
|
|
2863032d9a | ||
|
|
aada189b1b | ||
|
|
22ea4de66e | ||
|
|
9859617a74 | ||
|
|
0629c1929d | ||
|
|
6ec45396c3 | ||
|
|
b76a9b80fb | ||
|
|
f4bc58bbf7 | ||
|
|
09fdbb6f95 | ||
|
|
8ee7ed23e4 | ||
|
|
8d8a78cf88 | ||
|
|
f0652231cb | ||
|
|
d9aa760256 | ||
|
|
a65f375255 | ||
|
|
3ee58e2711 | ||
|
|
9b3b083aec | ||
|
|
ecb9b8f172 | ||
|
|
5765c27240 | ||
|
|
c53456112a | ||
|
|
ccea21886e | ||
|
|
37be8de5ac | ||
|
|
107e43a15f | ||
|
|
17b3ed34db | ||
|
|
cce9cd34af | ||
|
|
6a80f8ee5d | ||
|
|
edb7f0d0bd | ||
|
|
8e69375338 | ||
|
|
d24ae98fb0 | ||
|
|
111b3ea632 | ||
|
|
cc1e759972 | ||
|
|
ad0527ed73 | ||
|
|
8ffbb918ea | ||
|
|
c27a0dba65 | ||
|
|
ad8305c66d | ||
|
|
29fe12f094 | ||
|
|
9dbe4c5eaf | ||
|
|
1e9aca3807 | ||
|
|
895da23f7d | ||
|
|
f788a10879 | ||
|
|
9fe4be0467 | ||
|
|
b1a7d3a111 | ||
|
|
8b9fdaaa30 | ||
|
|
60d5947535 | ||
|
|
0ba0e64a2a | ||
|
|
e1dfd1f0d0 | ||
|
|
cd2a529381 | ||
|
|
6ba8dcac49 | ||
|
|
f2e76b5459 | ||
|
|
cfbf6ed021 | ||
|
|
a372eb5125 | ||
|
|
76b89ca0e8 | ||
|
|
2c1721d52c | ||
|
|
324a77a625 | ||
|
|
88e59b8ec9 | ||
|
|
df71a17d9f | ||
|
|
8451f53e19 | ||
|
|
e795af5c11 | ||
|
|
efa3c5175c | ||
|
|
32efe42a61 | ||
|
|
97d2d09cdc | ||
|
|
ed90d567a4 | ||
|
|
51d6fb0f42 | ||
|
|
c10525708c | ||
|
|
0a69d795aa | ||
|
|
3b1d6831a5 | ||
|
|
b4c1dbcddb | ||
|
|
db5d62d7c0 | ||
|
|
ed5ccf38c6 | ||
|
|
7671e0c04c | ||
|
|
f3b8221b29 | ||
|
|
8fdc9a67c0 | ||
|
|
bb2e739876 | ||
|
|
852cbff5f3 | ||
|
|
6e1c111876 | ||
|
|
9f60839e40 | ||
|
|
dd37db18b5 | ||
|
|
793d60f7b5 | ||
|
|
08674cd7a6 | ||
|
|
dca3e39a6d | ||
|
|
8a1033d4b6 | ||
|
|
e4ebe558d7 | ||
|
|
70728cc5ed | ||
|
|
b49a0a5ff4 | ||
|
|
b48d959ffb | ||
|
|
b8e1ad89af | ||
|
|
b2bfbfcd86 | ||
|
|
062e28a6d2 | ||
|
|
dc0f833291 | ||
|
|
e598237916 | ||
|
|
6b96d3d9e9 | ||
|
|
1dbb610846 | ||
|
|
5c649b0c15 | ||
|
|
527ab041d9 | ||
|
|
ff94e90259 | ||
|
|
51efbcce1e | ||
|
|
87b2345105 | ||
|
|
5022d33ca9 | ||
|
|
141f949a63 | ||
|
|
3913c71fd8 | ||
|
|
5706652c40 | ||
|
|
768b6b20f5 | ||
|
|
7066b7dbb6 | ||
|
|
17e01fc7b9 | ||
|
|
ee9fcf38b7 | ||
|
|
5abb24bdd4 | ||
|
|
53f17d3f22 | ||
|
|
b728c38dc1 | ||
|
|
5e57b6ecd0 | ||
|
|
e9ffcdf7c3 | ||
|
|
118657de7c | ||
|
|
34c332504b | ||
|
|
d7a29d68a1 | ||
|
|
eefa02837d | ||
|
|
5b2812fa61 | ||
|
|
e3ddfb88c1 | ||
|
|
664d94aeaa | ||
|
|
e2baf63099 | ||
|
|
c1b7000139 | ||
|
|
6e8333d76f | ||
|
|
c67eddc9d4 | ||
|
|
292cf6fd94 | ||
|
|
69038bca43 | ||
|
|
f05d15ce36 | ||
|
|
98cb349d67 | ||
|
|
a4314ee4d5 | ||
|
|
96097bd25a | ||
|
|
14029e6af2 | ||
|
|
365777141d | ||
|
|
aaa5da8d9b | ||
|
|
b898ab5679 | ||
|
|
b896fa5cc7 | ||
|
|
bca9f6d66b | ||
|
|
d6f71cb2eb | ||
|
|
986d09867c | ||
|
|
97cb2151f9 | ||
|
|
338ac100a1 | ||
|
|
01badcee6a | ||
|
|
302cf1114c | ||
|
|
613e03dc75 | ||
|
|
4267359cb2 | ||
|
|
daac8ec787 | ||
|
|
857adec459 | ||
|
|
b46e10a1a6 | ||
|
|
10799b7e9c | ||
|
|
6bbeaa1738 | ||
|
|
1a0f1cbf9a | ||
|
|
68e708fe96 | ||
|
|
a2166f2327 | ||
|
|
6d55366bdc | ||
|
|
28fcaa81cf | ||
|
|
c5efc2990e | ||
|
|
597010b9a1 | ||
|
|
1f71816256 | ||
|
|
7c3618d2b5 | ||
|
|
df9038039c | ||
|
|
9a4b23976a | ||
|
|
8732e0fe5e | ||
|
|
c23b84c4d5 | ||
|
|
345b6a792a | ||
|
|
d9ae52165d | ||
|
|
4f40e8328b | ||
|
|
ebdd828b06 | ||
|
|
711acb55db | ||
|
|
7dfc21bfe0 | ||
|
|
78644a6eec | ||
|
|
30b1d77575 | ||
|
|
a9626d03a4 | ||
|
|
be731bbffb | ||
|
|
8cd40e2de3 | ||
|
|
7745594bb6 | ||
|
|
e43bedf1c2 | ||
|
|
d6623a8646 | ||
|
|
403ba51a7d | ||
|
|
b185a606e6 | ||
|
|
342a9a4826 | ||
|
|
2df2e8a65e | ||
|
|
2d5e9231a9 | ||
|
|
818e2bf1d0 | ||
|
|
f0a876f7cc | ||
|
|
3fae8f91cb | ||
|
|
8b08056ca7 | ||
|
|
39eaf53deb | ||
|
|
4674d1d7e5 | ||
|
|
b8b5cc8b1d | ||
|
|
dc987233a7 | ||
|
|
266b400c22 | ||
|
|
a4ac083fd0 | ||
|
|
320dd16838 | ||
|
|
5c05c636bc | ||
|
|
7103a8a83a | ||
|
|
ad749d801a | ||
|
|
747e9a0490 | ||
|
|
836402bd0f | ||
|
|
a3d5e1ce1f | ||
|
|
f2cc59a4ab | ||
|
|
6ea77f7e05 | ||
|
|
5ea8df7cb9 | ||
|
|
c70e8ec90d | ||
|
|
210e3a8cb1 | ||
|
|
a0c3bb094c | ||
|
|
b4d932692a | ||
|
|
667534a07a | ||
|
|
159928f24b | ||
|
|
8a91ded610 | ||
|
|
4226b7eb32 | ||
|
|
b61c99dd1c | ||
|
|
1ccb0d5334 | ||
|
|
7fa01353dd | ||
|
|
4f849d880b | ||
|
|
4b60c96aad | ||
|
|
a4dc0d65cf | ||
|
|
85e017423f | ||
|
|
b38488937b | ||
|
|
d291d5825a | ||
|
|
9d6162f65f | ||
|
|
f54ab42a92 | ||
|
|
78c8ae3e8f | ||
|
|
c64830c5b6 | ||
|
|
561c7cf7b1 | ||
|
|
2c6862de41 | ||
|
|
69842cbadf | ||
|
|
c7327e7bb2 | ||
|
|
de33ed7fc4 | ||
|
|
c99bb8d074 | ||
|
|
a98e54ebc6 | ||
|
|
a832aa1925 | ||
|
|
c7eb5debcb | ||
|
|
91f0cb4e31 | ||
|
|
5e8407a6ab | ||
|
|
243c2c1536 | ||
|
|
930aca4ffe | ||
|
|
1639cabe8e | ||
|
|
5961a57c5b | ||
|
|
75d9bc6dec | ||
|
|
4ccca32881 | ||
|
|
a7f5d9dd96 | ||
|
|
c8ba125abc | ||
|
|
7d290031f1 | ||
|
|
5220a8c7ac | ||
|
|
33e221f60f | ||
|
|
7f77547c50 | ||
|
|
c5964e33ac | ||
|
|
1c6f3ec797 | ||
|
|
8601f61739 | ||
|
|
91bac0d50b | ||
|
|
0bf03e0fb5 | ||
|
|
81401178a5 | ||
|
|
882357a8e5 | ||
|
|
abf629c5c6 | ||
|
|
758f9004cd | ||
|
|
f174f8cbb3 | ||
|
|
f2f6bde25d | ||
|
|
85f378b303 | ||
|
|
71ab3fdefb | ||
|
|
2f83d6c860 | ||
|
|
3db4975b48 | ||
|
|
6a6eea5d02 | ||
|
|
8fe9eeb32f | ||
|
|
4c1025243b | ||
|
|
f24eb02ca1 | ||
|
|
b01c09491f | ||
|
|
54ae742899 | ||
|
|
4c862463d7 | ||
|
|
b455c89ddc | ||
|
|
782b76cd8e | ||
|
|
230c2d9457 | ||
|
|
63531e3b8c | ||
|
|
ac430305f4 | ||
|
|
3d830cfc16 | ||
|
|
b529aa8861 | ||
|
|
3798daa54e | ||
|
|
624380ed86 | ||
|
|
2b025e225b | ||
|
|
15a67ea28c | ||
|
|
c6b62fd5fd | ||
|
|
3c0877c1a0 | ||
|
|
967b57b9a8 | ||
|
|
f47cc319b5 | ||
|
|
26da84c4e7 | ||
|
|
a39e8dc5c6 | ||
|
|
1bb4669135 | ||
|
|
0203eef006 | ||
|
|
4ab50ee191 | ||
|
|
06c1ec1ac2 | ||
|
|
ef4befdc38 | ||
|
|
33f49ddffa | ||
|
|
49aa249b5b | ||
|
|
c387d44890 | ||
|
|
d4d09e7267 | ||
|
|
dd7bf02a97 | ||
|
|
6d0eeb478f | ||
|
|
d4e9de48b1 | ||
|
|
6bd9877925 | ||
|
|
d38df6596f | ||
|
|
b4e31e859c | ||
|
|
1acd07c1be | ||
|
|
b9b25bb098 | ||
|
|
5ea2981dc7 | ||
|
|
4fb96ca3a4 | ||
|
|
6de52f5585 | ||
|
|
6622e41f64 | ||
|
|
8405e4d1e5 | ||
|
|
0edc3f1560 | ||
|
|
c109fe7561 | ||
|
|
b5413dca5c | ||
|
|
6c2d4a1e70 | ||
|
|
be03f1a32d | ||
|
|
3ed1cc453a | ||
|
|
16030063ed | ||
|
|
458696ad8f | ||
|
|
6201702563 | ||
|
|
c5bea23a8f | ||
|
|
e5f38f77ef | ||
|
|
1d774ab8de | ||
|
|
bc66ca9948 | ||
|
|
524cd21fd4 | ||
|
|
132cb0e1f4 | ||
|
|
09c99e7731 | ||
|
|
c9d0be1117 | ||
|
|
965055c8d7 | ||
|
|
f6bb21d0ef | ||
|
|
465e0a4ce0 | ||
|
|
55f304b885 | ||
|
|
0cb1d97332 | ||
|
|
e2091cd82f | ||
|
|
d2bada4159 | ||
|
|
b27998d7f2 | ||
|
|
98d3e21db9 | ||
|
|
0683504330 | ||
|
|
98bd1b2de6 | ||
|
|
c169ca1684 | ||
|
|
88214ea166 | ||
|
|
4bdcd1a811 | ||
|
|
fa4f665a3e | ||
|
|
e59e022c0a | ||
|
|
d096dc696a | ||
|
|
071007c3e5 | ||
|
|
57192d5043 | ||
|
|
6af72683a8 | ||
|
|
3af9567506 | ||
|
|
1d7adf3944 | ||
|
|
fb7399adf8 | ||
|
|
6ebbffdda1 | ||
|
|
2c35333cac | ||
|
|
fe5e38b216 | ||
|
|
9fd7d8b62a | ||
|
|
a9aa73033f | ||
|
|
73dfca0bc0 | ||
|
|
cdc9b6b011 | ||
|
|
bbdd365a28 | ||
|
|
ec19ce6561 | ||
|
|
9e62860d8d | ||
|
|
4b6d6cf651 | ||
|
|
4af457710f | ||
|
|
f4dc05d7d0 |
+137
@@ -0,0 +1,137 @@
|
||||
[*.cs]
|
||||
|
||||
# CA2254: Template should be a static expression
|
||||
dotnet_diagnostic.CA2254.severity = none
|
||||
csharp_indent_labels = one_less_than_current
|
||||
csharp_using_directive_placement = outside_namespace:error
|
||||
csharp_prefer_simple_using_statement = true:error
|
||||
csharp_prefer_braces = true:silent
|
||||
csharp_style_namespace_declarations = file_scoped:error
|
||||
csharp_style_prefer_method_group_conversion = true:suggestion
|
||||
csharp_style_expression_bodied_methods = false:silent
|
||||
csharp_style_expression_bodied_constructors = false:silent
|
||||
csharp_style_expression_bodied_operators = false:silent
|
||||
csharp_style_expression_bodied_properties = true:silent
|
||||
csharp_style_expression_bodied_indexers = true:silent
|
||||
csharp_style_expression_bodied_accessors = true:silent
|
||||
csharp_style_expression_bodied_lambdas = true:silent
|
||||
csharp_style_expression_bodied_local_functions = false:silent
|
||||
csharp_indent_braces = false
|
||||
insert_final_newline = true
|
||||
csharp_space_around_binary_operators = before_and_after
|
||||
csharp_style_throw_expression = true:suggestion
|
||||
csharp_style_prefer_null_check_over_type_check = true:suggestion
|
||||
csharp_prefer_simple_default_expression = true:suggestion
|
||||
csharp_style_prefer_local_over_anonymous_function = true:error
|
||||
csharp_style_prefer_index_operator = true:suggestion
|
||||
csharp_style_prefer_range_operator = true:suggestion
|
||||
csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion
|
||||
csharp_style_prefer_tuple_swap = true:suggestion
|
||||
csharp_style_inlined_variable_declaration = true:suggestion
|
||||
csharp_style_deconstructed_variable_declaration = true:error
|
||||
csharp_style_unused_value_assignment_preference = discard_variable:error
|
||||
csharp_style_unused_value_expression_statement_preference = discard_variable:silent
|
||||
csharp_prefer_static_local_function = true:suggestion
|
||||
csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent
|
||||
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent
|
||||
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false:suggestion
|
||||
csharp_style_conditional_delegate_call = true:suggestion
|
||||
csharp_style_prefer_parameter_null_checking = true:suggestion
|
||||
csharp_style_prefer_switch_expression = true:suggestion
|
||||
csharp_style_prefer_pattern_matching = true:silent
|
||||
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
|
||||
csharp_style_prefer_not_pattern = true:suggestion
|
||||
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
|
||||
csharp_style_prefer_extended_property_pattern = true:suggestion
|
||||
csharp_style_var_for_built_in_types = false:silent
|
||||
csharp_style_var_when_type_is_apparent = false:silent
|
||||
csharp_style_var_elsewhere = false:silent
|
||||
csharp_style_prefer_top_level_statements = true:suggestion
|
||||
csharp_style_prefer_utf8_string_literals = true:suggestion
|
||||
csharp_style_prefer_readonly_struct = true:suggestion
|
||||
|
||||
[*.{cs,vb}]
|
||||
#### Naming styles ####
|
||||
|
||||
# Naming rules
|
||||
|
||||
dotnet_naming_rule.interface_should_be_begins_with_i.severity = error
|
||||
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
|
||||
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
|
||||
|
||||
dotnet_naming_rule.types_should_be_pascal_case.severity = error
|
||||
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
|
||||
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
|
||||
|
||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = error
|
||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
|
||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
|
||||
|
||||
# Symbol specifications
|
||||
|
||||
dotnet_naming_symbols.interface.applicable_kinds = interface
|
||||
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.interface.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
|
||||
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.types.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
|
||||
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.non_field_members.required_modifiers =
|
||||
|
||||
# Naming styles
|
||||
|
||||
dotnet_naming_style.begins_with_i.required_prefix = I
|
||||
dotnet_naming_style.begins_with_i.required_suffix =
|
||||
dotnet_naming_style.begins_with_i.word_separator =
|
||||
dotnet_naming_style.begins_with_i.capitalization = pascal_case
|
||||
|
||||
dotnet_naming_style.pascal_case.required_prefix =
|
||||
dotnet_naming_style.pascal_case.required_suffix =
|
||||
dotnet_naming_style.pascal_case.word_separator =
|
||||
dotnet_naming_style.pascal_case.capitalization = pascal_case
|
||||
|
||||
dotnet_naming_style.pascal_case.required_prefix =
|
||||
dotnet_naming_style.pascal_case.required_suffix =
|
||||
dotnet_naming_style.pascal_case.word_separator =
|
||||
dotnet_naming_style.pascal_case.capitalization = pascal_case
|
||||
dotnet_style_operator_placement_when_wrapping = beginning_of_line
|
||||
tab_width = 4
|
||||
indent_size = 4
|
||||
end_of_line = crlf
|
||||
dotnet_style_coalesce_expression = true:suggestion
|
||||
dotnet_style_null_propagation = true:suggestion
|
||||
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:error
|
||||
dotnet_style_prefer_auto_properties = true:error
|
||||
dotnet_style_object_initializer = true:suggestion
|
||||
dotnet_style_collection_initializer = true:suggestion
|
||||
dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
|
||||
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
|
||||
dotnet_style_prefer_conditional_expression_over_return = true:silent
|
||||
dotnet_style_explicit_tuple_names = true:suggestion
|
||||
dotnet_style_prefer_inferred_tuple_names = true:suggestion
|
||||
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
|
||||
dotnet_style_prefer_compound_assignment = true:suggestion
|
||||
dotnet_style_prefer_simplified_interpolation = true:suggestion
|
||||
dotnet_style_namespace_match_folder = true:suggestion
|
||||
dotnet_style_readonly_field = true:suggestion
|
||||
dotnet_style_predefined_type_for_locals_parameters_members = true:silent
|
||||
dotnet_style_predefined_type_for_member_access = true:silent
|
||||
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
|
||||
dotnet_style_allow_multiple_blank_lines_experimental = true:silent
|
||||
dotnet_style_allow_statement_immediately_after_block_experimental = false:suggestion
|
||||
dotnet_code_quality_unused_parameters = all:error
|
||||
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:suggestion
|
||||
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:suggestion
|
||||
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:suggestion
|
||||
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion
|
||||
dotnet_style_qualification_for_field = true:error
|
||||
dotnet_style_qualification_for_property = true:error
|
||||
dotnet_style_qualification_for_method = true:error
|
||||
dotnet_style_qualification_for_event = true:error
|
||||
dotnet_diagnostic.CA1000.severity = error
|
||||
|
||||
[*.vb]
|
||||
dotnet_diagnostic.CA1047.severity = error
|
||||
@@ -0,0 +1 @@
|
||||
* amacocian@yahoo.com
|
||||
@@ -0,0 +1,16 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
|
||||
- package-ecosystem: "nuget"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
@@ -0,0 +1,164 @@
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT license.
|
||||
|
||||
# This continuous integration pipeline is triggered anytime a user pushes code to the repo.
|
||||
# This pipeline builds the Wpf project, runs unit tests, then saves the MSIX build artifact.
|
||||
name: Daybreak CD Pipeline
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- "Daybreak/**"
|
||||
- "Daybreak.Installer/**"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
targetplatform: [x86]
|
||||
|
||||
runs-on: windows-latest
|
||||
|
||||
env:
|
||||
Configuration: Release
|
||||
Solution_Path: Daybreak.sln
|
||||
Test_Project_Path: Daybreak.Tests\Daybreak.Tests.csproj
|
||||
Wpf_Project_Path: Daybreak\Daybreak.csproj
|
||||
Actions_Allow_Unsecure_Commands: true
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get Latest Tag
|
||||
id: getLatestTag
|
||||
uses: WyriHaximus/github-action-get-previous-tag@v1
|
||||
|
||||
- name: Generate changelog
|
||||
id: gen_changelog
|
||||
run: |
|
||||
$changeLog = git log --no-merges --pretty="%h - %s (%an)<br />" ${{ env.LatestReleaseTag }}..HEAD
|
||||
echo "::set-env name=Changelog::$changeLog"
|
||||
mkdir Publish
|
||||
echo $changeLog > .\Publish\changelog.txt
|
||||
env:
|
||||
LatestReleaseTag: ${{steps.getLatestTag.outputs.tag}}
|
||||
|
||||
- name: Install .NET Core
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: '9.x'
|
||||
|
||||
- name: Setup MSBuild.exe
|
||||
uses: microsoft/setup-msbuild@v2.0.0
|
||||
|
||||
- name: Setup project secrets
|
||||
run: |
|
||||
dotnet user-secrets --project Daybreak\Daybreak.csproj set AadApplicationId "${{ secrets.AadApplicationId }}"
|
||||
dotnet user-secrets --project Daybreak\Daybreak.csproj set AadTenantId "${{ secrets.AadTenantId }}"
|
||||
|
||||
- name: Restore project
|
||||
run: msbuild $env:Solution_Path /t:Restore /p:Configuration=$env:Configuration /p:RuntimeIdentifier=$env:RuntimeIdentifier --property:SolutionDir=$GITHUB_WORKSPACE
|
||||
env:
|
||||
RuntimeIdentifier: win-${{ matrix.targetplatform }}
|
||||
|
||||
- name: Build Daybreak project
|
||||
run: dotnet build Daybreak -c $env:Configuration --property:SolutionDir=$env:GITHUB_WORKSPACE
|
||||
|
||||
- name: Set version variable
|
||||
run: |
|
||||
$version = .\Scripts\GetBuildVersion.ps1
|
||||
echo "::set-env name=Version::$version"
|
||||
|
||||
- name: Create publish launcher files
|
||||
run: dotnet publish .\Daybreak\Daybreak.csproj -c $env:Configuration -r $env:RuntimeIdentifier --property:SolutionDir=$env:GITHUB_WORKSPACE -p:PublishReadyToRun=true -p:PublishSingleFile=false --self-contained true -o .\Publish
|
||||
env:
|
||||
RuntimeIdentifier: win-${{ matrix.targetplatform }}
|
||||
|
||||
- name: Create publish installer files
|
||||
run: dotnet publish .\Daybreak.Installer\Daybreak.Installer.csproj -c $env:Configuration -r $env:RuntimeIdentifier --property:SolutionDir=$env:GITHUB_WORKSPACE -p:PublishReadyToRun=true -p:PublishSingleFile=true --self-contained true -o .\Publish
|
||||
env:
|
||||
RuntimeIdentifier: win-${{ matrix.targetplatform }}
|
||||
|
||||
- name: Create publish extractor files
|
||||
run: dotnet publish .\Daybreak.7ZipExtractor\Daybreak.7ZipExtractor.csproj -c $env:Configuration -r $env:RuntimeIdentifier --property:SolutionDir=$env:GITHUB_WORKSPACE -p:PublishReadyToRun=true -p:PublishSingleFile=false --self-contained true -o .\Publish
|
||||
env:
|
||||
RuntimeIdentifier: win-${{ matrix.targetplatform }}
|
||||
|
||||
- name: Pack publish files
|
||||
run: |
|
||||
Write-Host $env
|
||||
.\Scripts\BuildRelease.ps1 -version $env:Version
|
||||
shell: pwsh
|
||||
|
||||
- name: Submit virustotal scan
|
||||
shell: pwsh
|
||||
run: |
|
||||
cd Publish
|
||||
$apiKey = "${{ secrets.VIRUSTOTAL_APIKEY }}"
|
||||
$archiveName = "daybreakv${{ env.Version }}.zip"
|
||||
$uploadUrlResponse = curl https://www.virustotal.com/api/v3/files/upload_url -H x-apikey:"$apiKey"
|
||||
$uploadUrlResponse
|
||||
$uploadUrlJson = $uploadUrlResponse | ConvertFrom-Json
|
||||
$uploadUrl = $uploadUrlJson.data
|
||||
$uploadResponse = curl --request POST --header x-apikey:"$apiKey" --header 'content-type: multipart/form-data' --form file="@$archiveName" --url $uploadUrl
|
||||
$uploadResponse
|
||||
$uploadResponseJson = $uploadResponse | ConvertFrom-Json
|
||||
$resultsUrl = "https://www.virustotal.com/api/v3/analyses/$($uploadResponseJson.data.id)"
|
||||
$resultsUrl
|
||||
# Poll the results until the status is "completed"
|
||||
$status = ""
|
||||
while ($status -ne "completed") {
|
||||
Start-Sleep -Seconds 10 # Wait for 10 seconds between checks
|
||||
$results = curl --header x-apikey:"$apiKey" --url $resultsUrl
|
||||
$results
|
||||
$resultsJson = $results | ConvertFrom-Json
|
||||
$status = $resultsJson.data.attributes.status
|
||||
Write-Host "Current status: $status"
|
||||
}
|
||||
|
||||
$resultsJson.data.attributes.results | ConvertTo-Json | Out-File -FilePath "VirusTotal.Results.json" -Encoding UTF8
|
||||
$resultsJson.data.attributes.stats | ConvertTo-Json | Out-File -FilePath "VirusTotal.Stats.json" -Encoding UTF8
|
||||
$stats = $resultsJson.data.attributes.stats
|
||||
echo "::set-env name=VirusTotalStats::$stats"
|
||||
|
||||
- name: Publish blob files
|
||||
run: |
|
||||
Write-Host $env
|
||||
.\Scripts\PushFilesToBlobStorage.ps1 -version $env:Version -sourcePath .\Publish\ -connectionString "${{ secrets.BLOBSTORAGE_CONNECTIONSTRING }}"
|
||||
shell: pwsh
|
||||
|
||||
- name: Create release draft
|
||||
uses: Xotl/cool-github-releases@v1.1.10
|
||||
with:
|
||||
mode: update
|
||||
tag_name: v${{ env.Version }}
|
||||
release_name: Daybreak v${{ env.Version }}
|
||||
assets: .\Publish\daybreakv${{ env.Version }}.zip;.\Publish\VirusTotal.Results.json;.\Publish\VirusTotal.Stats.json
|
||||
github_token: ${{ env.GITHUB_TOKEN }}
|
||||
replace_assets: true
|
||||
body_mrkdwn: |
|
||||
${{ env.Changelog }}
|
||||
|
||||
** VirustTotal Stats: **
|
||||
```
|
||||
${{ env.VirusTotalStats }}
|
||||
```
|
||||
isDraft: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Publish release
|
||||
run: |
|
||||
gh release edit v${{ env.Version }} --draft=false
|
||||
shell: powershell
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT license.
|
||||
|
||||
# This continuous integration pipeline is triggered anytime a user pushes code to the repo.
|
||||
# This pipeline builds the Wpf project, runs unit tests, then saves the MSIX build artifact.
|
||||
name: Daybreak CI Pipeline
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
targetplatform: [x86]
|
||||
|
||||
runs-on: windows-latest
|
||||
|
||||
env:
|
||||
Solution_Path: Daybreak.sln
|
||||
Test_Project_Path: Daybreak.Tests\Daybreak.Tests.csproj
|
||||
Wpf_Project_Path: Daybreak\Daybreak.csproj
|
||||
Actions_Allow_Unsecure_Commands: true
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install .NET Core
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: '9.x'
|
||||
|
||||
- name: Setup MSBuild.exe
|
||||
uses: microsoft/setup-msbuild@v2.0.0
|
||||
|
||||
- name: Execute Unit Tests
|
||||
run: dotnet test $env:Test_Project_Path --property:SolutionDir=$env:GITHUB_WORKSPACE -p:ParallelizeTestCollections=false
|
||||
|
||||
- name: Restore the Wpf application to populate the obj folder
|
||||
run: msbuild $env:Solution_Path /t:Restore /p:Configuration=$env:Configuration /p:RuntimeIdentifier=$env:RuntimeIdentifier --property:SolutionDir=$env:GITHUB_WORKSPACE
|
||||
env:
|
||||
Configuration: Debug
|
||||
RuntimeIdentifier: win-${{ matrix.targetplatform }}
|
||||
@@ -0,0 +1,90 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ "master" ]
|
||||
schedule:
|
||||
- cron: '41 12 * * 6'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: windows-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'csharp' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||
|
||||
env:
|
||||
Configuration: Release
|
||||
Solution_Path: Daybreak.sln
|
||||
Test_Project_Path: Daybreak.Tests\Daybreak.Tests.csproj
|
||||
Wpf_Project_Path: Daybreak\Daybreak.csproj
|
||||
Actions_Allow_Unsecure_Commands: true
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
|
||||
- name: Install .NET Core
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: '9.x'
|
||||
|
||||
#- name: Autobuild
|
||||
# uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
|
||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||
|
||||
# - run: |
|
||||
# echo "Run, Build Application using script"
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
|
||||
- name: Build Daybreak project
|
||||
run: dotnet build Daybreak -c $env:Configuration --property:SolutionDir=$env:GITHUB_WORKSPACE
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
@@ -0,0 +1,53 @@
|
||||
name: Daybreak Version Check
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- "Daybreak/**"
|
||||
- "Daybreak.Installer/**"
|
||||
|
||||
jobs:
|
||||
|
||||
check_version:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
targetplatform: [x86]
|
||||
|
||||
runs-on: windows-latest
|
||||
|
||||
env:
|
||||
Configuration: Release
|
||||
Solution_Path: Daybreak.sln
|
||||
Actions_Allow_Unsecure_Commands: true
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install .NET Core
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: '9.x'
|
||||
|
||||
- name: Get Latest Tag
|
||||
id: getLatestTag
|
||||
uses: WyriHaximus/github-action-get-previous-tag@v1
|
||||
|
||||
- name: Build Daybreak project
|
||||
run: dotnet build Daybreak -c $env:Configuration --property:SolutionDir=$env:GITHUB_WORKSPACE
|
||||
|
||||
- name: Set version variable
|
||||
run: |
|
||||
$version = .\Scripts\GetBuildVersion.ps1
|
||||
echo "::set-env name=Version::$version"
|
||||
|
||||
- name: Check version difference
|
||||
run: |
|
||||
.\Scripts\CompareVersions -currentVersion ${{ env.Version }} -lastVersion ${{ env.LatestReleaseTag }}
|
||||
env:
|
||||
LatestReleaseTag: ${{ steps.getLatestTag.outputs.tag }}
|
||||
+5
-1
@@ -9,6 +9,7 @@
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
*.version
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
@@ -27,6 +28,7 @@ x86/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
build/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Oo]ut/
|
||||
@@ -360,4 +362,6 @@ MigrationBackup/
|
||||
.ionide/
|
||||
|
||||
# Fody - auto-generated XML schema
|
||||
FodyWeavers.xsd
|
||||
FodyWeavers.xsd
|
||||
|
||||
.idea
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<RootNamespace>Daybreak._7ZipExtractor</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SharpCompress" Version="0.39.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Extractor is in a different executable because of memory limitations. Daybreak needs to be compiled for x86 and as such has a memory limit of 2GB.
|
||||
* 7Zip algorithm may require more than 2GB memory to unpack large zip files.
|
||||
* As such, Daybreak.7ZipExtractor is x64.
|
||||
*/
|
||||
using SharpCompress.Archives;
|
||||
|
||||
if (args.Length != 2)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
var archivePath = args[0];
|
||||
var destinationDirectory = args[1];
|
||||
|
||||
using var fileStream = new FileStream(archivePath, FileMode.Open);
|
||||
using var archive = ArchiveFactory.Open(fileStream);
|
||||
var progress = 0d;
|
||||
var count = archive.Entries.Count();
|
||||
var reader = archive.ExtractAllEntries();
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
var entry = reader.Entry;
|
||||
if (entry.IsDirectory)
|
||||
{
|
||||
var directoryName = Path.Combine(Path.GetFullPath(destinationDirectory), entry.Key);
|
||||
Directory.CreateDirectory(directoryName);
|
||||
continue;
|
||||
}
|
||||
|
||||
var fileName = Path.Combine(Path.GetFullPath(destinationDirectory), entry.Key);
|
||||
using var entryStream = new FileStream(fileName, FileMode.Create);
|
||||
using (var stream = reader.OpenEntryStream())
|
||||
{
|
||||
stream.CopyTo(entryStream);
|
||||
}
|
||||
|
||||
progress += 1d / count;
|
||||
Console.WriteLine($"{progress} {fileName}");
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Platforms>AnyCPU;x86</Platforms>
|
||||
<PublishSingleFile>True</PublishSingleFile>
|
||||
<Self-Contained>True</Self-Contained>
|
||||
<PublishReadyToRun>True</PublishReadyToRun>
|
||||
<RuntimeIdentifier>win-x86</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,129 @@
|
||||
// See https://aka.ms/new-console-template for more information
|
||||
using System.Diagnostics;
|
||||
using System.IO.Compression;
|
||||
using System.Text;
|
||||
|
||||
static void RenderProgressBar(int currentStep, int totalSteps, int barSize)
|
||||
{
|
||||
Console.CursorLeft = 0; // Reset cursor position to the start of the line
|
||||
Console.Write("["); // Start of the progress bar
|
||||
|
||||
double pctComplete = (double)currentStep / totalSteps;
|
||||
int chars = (int)Math.Round(pctComplete * barSize);
|
||||
|
||||
Console.Write(new string('=', chars)); // The 'completed' part of the bar
|
||||
Console.Write(new string(' ', barSize - chars)); // The 'remaining' part of the bar
|
||||
|
||||
Console.Write("] ");
|
||||
Console.Write($"{pctComplete:P0}"); // Display the percentage completed
|
||||
}
|
||||
|
||||
const string tempFile = "tempfile.zip";
|
||||
const string updatePkg = "update.pkg";
|
||||
const string executableName = "Daybreak.exe";
|
||||
Console.Title = "Daybreak Installer";
|
||||
Console.WriteLine("Starting installation...");
|
||||
while (Process.GetProcesses().Where(p => p.ProcessName == "Daybreak").FirstOrDefault()?.HasExited is false)
|
||||
{
|
||||
Console.WriteLine($"Detected Daybreak process is still running. Waiting 5s and retrying");
|
||||
await Task.Delay(5000);
|
||||
}
|
||||
|
||||
if (File.Exists(updatePkg))
|
||||
{
|
||||
Console.WriteLine("Unpacking files...");
|
||||
|
||||
using var fileStream = new FileStream(updatePkg, FileMode.Open);
|
||||
var sizeBuffer = new byte[4];
|
||||
var copyBuffer = new byte[1024];
|
||||
while (fileStream.Position < fileStream.Length - 1)
|
||||
{
|
||||
/*
|
||||
* For each file downloaded, we write to the package the following:
|
||||
* Size of the name string
|
||||
* UTF-8 encoded name string
|
||||
* Size of the relative path string
|
||||
* UTF-8 encoded relative path string
|
||||
* Size of the binary
|
||||
* Binary data
|
||||
*/
|
||||
|
||||
await fileStream.ReadAsync(sizeBuffer, 0, 4);
|
||||
var fileNameSize = BitConverter.ToInt32(sizeBuffer, 0);
|
||||
var fileNameBuffer = new byte[fileNameSize];
|
||||
await fileStream.ReadAsync(fileNameBuffer, 0, fileNameSize);
|
||||
var fileName = Encoding.UTF8.GetString(fileNameBuffer);
|
||||
|
||||
RenderProgressBar((int)fileStream.Position, (int)fileStream.Length, 40);
|
||||
|
||||
await fileStream.ReadAsync(sizeBuffer, 0, 4);
|
||||
var relativePathSize = BitConverter.ToInt32(sizeBuffer, 0);
|
||||
var relativePathBuffer = new byte[relativePathSize];
|
||||
await fileStream.ReadAsync(relativePathBuffer, 0, relativePathSize);
|
||||
var relativePath = Encoding.UTF8.GetString(relativePathBuffer);
|
||||
|
||||
RenderProgressBar((int)fileStream.Position, (int)fileStream.Length, 40);
|
||||
|
||||
await fileStream.ReadAsync(sizeBuffer, 0, 4);
|
||||
var binarySize = BitConverter.ToInt32(sizeBuffer, 0);
|
||||
var fileInfo = new FileInfo(relativePath);
|
||||
fileInfo.Directory!.Create();
|
||||
using var destinationStream = new FileStream(relativePath, FileMode.Create);
|
||||
while(binarySize > 0)
|
||||
{
|
||||
var toRead = Math.Min(binarySize, copyBuffer.Length);
|
||||
await fileStream.ReadAsync(copyBuffer, 0, toRead);
|
||||
await destinationStream.WriteAsync(copyBuffer, 0, toRead);
|
||||
binarySize -= toRead;
|
||||
|
||||
RenderProgressBar((int)fileStream.Position, (int)fileStream.Length, 40);
|
||||
}
|
||||
}
|
||||
|
||||
fileStream.Close();
|
||||
fileStream.Dispose();
|
||||
File.Delete(updatePkg);
|
||||
}
|
||||
else if (File.Exists(tempFile))
|
||||
{
|
||||
Console.WriteLine("Unpacking files...");
|
||||
try
|
||||
{
|
||||
ZipFile.ExtractToDirectory(tempFile, AppContext.BaseDirectory, true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
Console.WriteLine("Deleting package");
|
||||
try
|
||||
{
|
||||
File.Delete(tempFile);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine($"Failed to delete {tempFile}.\n{e}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine("Unable to find launcher package. Aborting installation");
|
||||
Console.ReadKey();
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine("Launching application");
|
||||
var process = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = executableName
|
||||
}
|
||||
};
|
||||
|
||||
if (process.Start() is false)
|
||||
{
|
||||
Console.WriteLine("Failed to launch application");
|
||||
Console.ReadKey();
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0-windows</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<Platforms>AnyCPU;x86;x64</Platforms>
|
||||
<RuntimeIdentifier>win-x86</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" Version="8.2.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.8.3" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.8.3" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||
<PackageReference Include="NSubstitute.Analyzers.CSharp" Version="1.0.17">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Linq.Async" Version="6.0.1" />
|
||||
<PackageReference Include="System.Private.Uri" Version="4.3.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Daybreak\Daybreak.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,15 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Collections.Generic;
|
||||
using System.Extensions;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Daybreak.Tests.Models;
|
||||
|
||||
[TestClass]
|
||||
public sealed class InscriptionTests : ItemTestsBase<Inscription>
|
||||
{
|
||||
protected override IEnumerable<Inscription> AllItems { get; } = Inscription.Inscriptions;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using FluentAssertions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Daybreak.Tests.Models;
|
||||
|
||||
[TestClass]
|
||||
public sealed class ItemBaseTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void TryParse_UnknownId_Fails()
|
||||
{
|
||||
var found = ItemBase.TryParse(int.MaxValue, modifiers: default, out var item);
|
||||
found.Should().BeFalse();
|
||||
item.Should().BeNull();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Parse_UnknownId_ThrowsInvalidOperationException()
|
||||
{
|
||||
var action = () => ItemBase.Parse(int.MaxValue, modifiers: default);
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TryParse_KnownId_Succeeds()
|
||||
{
|
||||
var found = ItemBase.TryParse(Inscription.WeaponInscription.Id, Inscription.WeaponInscription.Modifiers, out var inscription);
|
||||
found.Should().BeTrue();
|
||||
inscription.Should().Be(Inscription.WeaponInscription);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Parse_KnownId_ReturnsExpected()
|
||||
{
|
||||
var inscription = ItemBase.Parse(Inscription.WeaponInscription.Id, Inscription.WeaponInscription.Modifiers);
|
||||
inscription.Should().Be(Inscription.WeaponInscription);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ItemList_Should_ContainOnlyUniqueItems()
|
||||
{
|
||||
var itemMap = new Dictionary<ItemBase, int>();
|
||||
|
||||
foreach (var item in ItemBase.AllItems)
|
||||
{
|
||||
if (!itemMap.TryGetValue(item, out _))
|
||||
{
|
||||
itemMap[item] = 0;
|
||||
}
|
||||
|
||||
itemMap[item] += 1;
|
||||
}
|
||||
|
||||
var errorMessage = new StringBuilder("Duplicated item entries: ");
|
||||
foreach (var tuple in itemMap)
|
||||
{
|
||||
if (tuple.Value > 1)
|
||||
{
|
||||
errorMessage.Append(tuple.Key.Name);
|
||||
errorMessage.Append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
if (itemMap.Any(kvp => kvp.Value > 1))
|
||||
{
|
||||
Assert.Fail(errorMessage.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Collections.Generic;
|
||||
using System.Extensions;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Daybreak.Tests.Models;
|
||||
|
||||
public abstract class ItemTestsBase<T>
|
||||
where T : ItemBase
|
||||
{
|
||||
protected abstract IEnumerable<T> AllItems { get; }
|
||||
|
||||
[TestMethod]
|
||||
public void List_Should_ContainOnlyUniqueItems()
|
||||
{
|
||||
var itemMap = new Dictionary<T, int>();
|
||||
|
||||
foreach (var item in this.AllItems)
|
||||
{
|
||||
if (!itemMap.TryGetValue(item, out _))
|
||||
{
|
||||
itemMap[item] = 0;
|
||||
}
|
||||
|
||||
itemMap[item] += 1;
|
||||
}
|
||||
|
||||
var errorMessage = new StringBuilder($"Duplicated {typeof(T).Name} entries: ");
|
||||
foreach (var tuple in itemMap)
|
||||
{
|
||||
if (tuple.Value > 1)
|
||||
{
|
||||
errorMessage.Append(tuple.Key.Name);
|
||||
errorMessage.Append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
if (itemMap.Any(kvp => kvp.Value > 1))
|
||||
{
|
||||
Assert.Fail(errorMessage.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void List_Should_ContainAllItems()
|
||||
{
|
||||
var itemMap = new Dictionary<T, bool>();
|
||||
var definedItemFields = typeof(T).GetFields(BindingFlags.Static | BindingFlags.Public).Where(f => f.FieldType == typeof(T));
|
||||
foreach (var field in definedItemFields)
|
||||
{
|
||||
var item = field.GetValue(default).Cast<T>();
|
||||
itemMap[item] = false;
|
||||
}
|
||||
|
||||
foreach (var item in this.AllItems)
|
||||
{
|
||||
itemMap[item] = true;
|
||||
}
|
||||
|
||||
var errorMessage = new StringBuilder($"{typeof(T).Name} entries not in list: ");
|
||||
foreach (var tuple in itemMap)
|
||||
{
|
||||
if (tuple.Value is false)
|
||||
{
|
||||
errorMessage.Append(tuple.Key.Name);
|
||||
errorMessage.Append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
if (itemMap.Any(kvp => kvp.Value is false))
|
||||
{
|
||||
Assert.Fail(errorMessage.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Daybreak.Tests.Models;
|
||||
|
||||
[TestClass]
|
||||
public sealed class MaterialTests : ItemTestsBase<Material>
|
||||
{
|
||||
protected override IEnumerable<Material> AllItems { get; } = Material.All;
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using FluentAssertions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Extensions;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Daybreak.Tests.Models;
|
||||
|
||||
[TestClass]
|
||||
public sealed class NpcTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void TryParse_UnknownId_Fails()
|
||||
{
|
||||
var found = Npc.TryParse(int.MaxValue, out var npc);
|
||||
found.Should().BeFalse();
|
||||
npc.Should().BeNull();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Parse_UnknownId_ThrowsInvalidOperationException()
|
||||
{
|
||||
var action = () => Npc.Parse(int.MaxValue);
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TryParse_KnownId_Succeeds()
|
||||
{
|
||||
var found = Npc.TryParse(Npc.Kormir.Ids.FirstOrDefault(), out var npc);
|
||||
found.Should().BeTrue();
|
||||
npc.Should().Be(Npc.Kormir);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Parse_KnownId_ReturnsExpected()
|
||||
{
|
||||
var npc = Npc.Parse(Npc.Kormir.Ids.FirstOrDefault());
|
||||
npc.Should().Be(Npc.Kormir);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void NpcList_Should_ContainOnlyUniqueItems()
|
||||
{
|
||||
var npcMap = new Dictionary<string, int>();
|
||||
|
||||
foreach(var npc in Npc.Npcs)
|
||||
{
|
||||
if (!npcMap.TryGetValue(npc.Name.ToLower(), out _))
|
||||
{
|
||||
npcMap[npc.Name.ToLower()] = 0;
|
||||
}
|
||||
|
||||
npcMap[npc.Name.ToLower()] += 1;
|
||||
}
|
||||
|
||||
var errorMessage = new StringBuilder("Duplicated npc entries: ");
|
||||
foreach(var tuple in npcMap)
|
||||
{
|
||||
if (tuple.Value > 1)
|
||||
{
|
||||
errorMessage.Append(tuple.Key);
|
||||
errorMessage.Append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
if (npcMap.Any(kvp => kvp.Value > 1))
|
||||
{
|
||||
Assert.Fail(errorMessage.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void NpcList_Should_ContainAllNpcs()
|
||||
{
|
||||
var npcMap = new Dictionary<Npc, bool>();
|
||||
var definedNpcsFields = typeof(Npc).GetFields(BindingFlags.Static | BindingFlags.Public).Where(f => f.FieldType == typeof(Npc));
|
||||
foreach(var field in definedNpcsFields)
|
||||
{
|
||||
var npc = field.GetValue(default).Cast<Npc>();
|
||||
npcMap[npc] = false;
|
||||
}
|
||||
|
||||
foreach(var npc in Npc.Npcs)
|
||||
{
|
||||
npcMap[npc] = true;
|
||||
}
|
||||
|
||||
var errorMessage = new StringBuilder("Npcs not in list: ");
|
||||
foreach(var tuple in npcMap)
|
||||
{
|
||||
if (tuple.Value is false)
|
||||
{
|
||||
errorMessage.Append(tuple.Key.Name);
|
||||
errorMessage.Append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
if (npcMap.Any(kvp => kvp.Value is false))
|
||||
{
|
||||
Assert.Fail(errorMessage.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using FluentAssertions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Extensions;
|
||||
|
||||
namespace Daybreak.Tests.Models;
|
||||
|
||||
[TestClass]
|
||||
public sealed class QuestTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void TryParse_UnknownId_Fails()
|
||||
{
|
||||
var found = Quest.TryParse(int.MaxValue, out var quest);
|
||||
found.Should().BeFalse();
|
||||
quest.Should().BeNull();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Parse_UnknownId_ThrowsInvalidOperationException()
|
||||
{
|
||||
var action = () => Quest.Parse(int.MaxValue);
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TryParse_KnownId_Succeeds()
|
||||
{
|
||||
var found = Quest.TryParse(Quest.RaisuPalaceZaishenQuest.Id, out var quest);
|
||||
found.Should().BeTrue();
|
||||
quest.Should().Be(Quest.RaisuPalaceZaishenQuest);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Parse_KnownId_ReturnsExpected()
|
||||
{
|
||||
var quest = Quest.Parse(Quest.RaisuPalaceZaishenQuest.Id);
|
||||
quest.Should().Be(Quest.RaisuPalaceZaishenQuest);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void QuestList_Should_ContainOnlyUniqueItems()
|
||||
{
|
||||
var questMap = new Dictionary<int, int>();
|
||||
|
||||
foreach (var quest in Quest.Quests)
|
||||
{
|
||||
if (!questMap.TryGetValue(quest.Id, out _))
|
||||
{
|
||||
questMap[quest.Id] = 0;
|
||||
}
|
||||
|
||||
questMap[quest.Id] += 1;
|
||||
}
|
||||
|
||||
var errorMessage = new StringBuilder("Duplicated quest entries: ");
|
||||
foreach (var tuple in questMap)
|
||||
{
|
||||
if (tuple.Value > 1)
|
||||
{
|
||||
errorMessage.Append(tuple.Key);
|
||||
errorMessage.Append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
if (questMap.Any(kvp => kvp.Value > 1))
|
||||
{
|
||||
Assert.Fail(errorMessage.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void QuestList_Should_ContainAllNpcs()
|
||||
{
|
||||
var questMap = new Dictionary<Quest, bool>();
|
||||
var definedNpcsFields = typeof(Quest).GetFields(BindingFlags.Static | BindingFlags.Public).Where(f => f.FieldType == typeof(Quest));
|
||||
foreach (var field in definedNpcsFields)
|
||||
{
|
||||
var quest = field.GetValue(default).Cast<Quest>();
|
||||
questMap[quest] = false;
|
||||
}
|
||||
|
||||
foreach (var quest in Quest.Quests)
|
||||
{
|
||||
questMap[quest] = true;
|
||||
}
|
||||
|
||||
var errorMessage = new StringBuilder("Quests not in list: ");
|
||||
foreach (var tuple in questMap)
|
||||
{
|
||||
if (tuple.Value is false)
|
||||
{
|
||||
errorMessage.Append(tuple.Key.Name);
|
||||
errorMessage.Append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
if (questMap.Any(kvp => kvp.Value is false))
|
||||
{
|
||||
Assert.Fail(errorMessage.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Daybreak.Tests.Models;
|
||||
|
||||
[TestClass]
|
||||
public sealed class RuneTests : ItemTestsBase<Rune>
|
||||
{
|
||||
protected override IEnumerable<Rune> AllItems { get; } = Rune.Runes;
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
using Daybreak.Models.Versioning;
|
||||
using FluentAssertions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Version = Daybreak.Models.Versioning.Version;
|
||||
|
||||
namespace Daybreak.Tests.Models;
|
||||
|
||||
[TestClass]
|
||||
public class VersionTests
|
||||
{
|
||||
[DataRow("v0.1.0.0.1", "v0.1.0.0.1")]
|
||||
[DataRow("v0.1.0.0.1.0.0.0.0", "v0.1.0.0.1")]
|
||||
[DataRow("v0.1.0", "v0.1")]
|
||||
[DataRow("0.1.0", "0.1")]
|
||||
[DataRow("v0.1.0.0.0", "v0.1")]
|
||||
[DataRow("0.1.0.0.0", "0.1")]
|
||||
[DataRow("v0", "v0")]
|
||||
[DataRow("0", "0")]
|
||||
[DataRow("v0.1", "v0.1")]
|
||||
[DataRow("0.1-release", "0.1-release")]
|
||||
[DataRow("v0.1-release", "v0.1-release")]
|
||||
[TestMethod]
|
||||
public void VersionToString(string version, string expectedString)
|
||||
{
|
||||
var parsedVersion = Version.Parse(version);
|
||||
parsedVersion.ToString().Should().Be(expectedString);
|
||||
}
|
||||
|
||||
[DataRow("v0", false)]
|
||||
[DataRow("0", false)]
|
||||
[DataRow("v0.1", false)]
|
||||
[DataRow("0.1-release", true)]
|
||||
[DataRow("v0.1-release", true)]
|
||||
[TestMethod]
|
||||
public void VersionHasStringSuffix(string version, bool hasSuffix)
|
||||
{
|
||||
var parsedVersion = Version.Parse(version);
|
||||
if (hasSuffix)
|
||||
{
|
||||
parsedVersion.VersionTokens.Last().Should().BeOfType<VersionStringToken>();
|
||||
}
|
||||
else
|
||||
{
|
||||
parsedVersion.VersionTokens.Last().Should().BeOfType<VersionNumberToken>();
|
||||
}
|
||||
}
|
||||
|
||||
[DataRow("v0", true)]
|
||||
[DataRow("0", false)]
|
||||
[DataRow("v0.1", true)]
|
||||
[DataRow("0.1", false)]
|
||||
[TestMethod]
|
||||
public void VersionTokensHasPrefix(string version, bool hasPrefix)
|
||||
{
|
||||
var parsedVersion = Version.Parse(version);
|
||||
parsedVersion.HasPrefix.Should().Be(hasPrefix);
|
||||
}
|
||||
|
||||
[DataRow(null, false)]
|
||||
[DataRow("", false)]
|
||||
[DataRow("asd", false)]
|
||||
[DataRow("ads.pls.er", false)]
|
||||
[DataRow("0.0.1", true)]
|
||||
[DataRow("1", true)]
|
||||
[DataRow("0.1.asd", false)]
|
||||
[DataRow("0.", false)]
|
||||
[DataRow(".1", false)]
|
||||
[DataRow("0.1-", false)]
|
||||
[DataRow("0.1-release", true)]
|
||||
[DataRow("0..1", false)]
|
||||
[TestMethod]
|
||||
public void TryParseVersionTest(string version, bool result)
|
||||
{
|
||||
var success = Version.TryParse(version, out var parsedVersion);
|
||||
success.Should().Be(result);
|
||||
if (success is true)
|
||||
{
|
||||
parsedVersion.Should().NotBeNull();
|
||||
}
|
||||
}
|
||||
|
||||
[DataRow(null, false)]
|
||||
[DataRow("", false)]
|
||||
[DataRow("asd", false)]
|
||||
[DataRow("ads.pls.er", false)]
|
||||
[DataRow("0.0.1", true)]
|
||||
[DataRow("1", true)]
|
||||
[DataRow("0.1.asd", false)]
|
||||
[DataRow("0.", false)]
|
||||
[DataRow(".1", false)]
|
||||
[DataRow("0.1-", false)]
|
||||
[DataRow("0.1-release", true)]
|
||||
[DataRow("0..1", false)]
|
||||
[TestMethod]
|
||||
public void ParseVersionTest(string version, bool shouldNotThrow)
|
||||
{
|
||||
var action = new Action(() => Version.Parse(version));
|
||||
if (shouldNotThrow is false)
|
||||
{
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
}
|
||||
else
|
||||
{
|
||||
action.Should().NotThrow<InvalidOperationException>();
|
||||
}
|
||||
}
|
||||
|
||||
[DataRow(null, false)]
|
||||
[DataRow("", false)]
|
||||
[DataRow("asd", false)]
|
||||
[DataRow("ads.pls.er", false)]
|
||||
[DataRow("0.0.1", true)]
|
||||
[DataRow("1", true)]
|
||||
[DataRow("0.1.asd", false)]
|
||||
[DataRow("0.", false)]
|
||||
[DataRow(".1", false)]
|
||||
[DataRow("0.1-", false)]
|
||||
[DataRow("0.1-release", true)]
|
||||
[DataRow("0..1", false)]
|
||||
[TestMethod]
|
||||
public void VersionConstructorTest(string version, bool shouldNotThrow)
|
||||
{
|
||||
var action = new Action(() => new Version(version));
|
||||
if (shouldNotThrow is false)
|
||||
{
|
||||
action.Should().Throw<ArgumentException>();
|
||||
}
|
||||
else
|
||||
{
|
||||
action.Should().NotThrow<ArgumentException>();
|
||||
}
|
||||
}
|
||||
|
||||
[DataRow("v0.1.0.0.1", "v0.1.0.0.1", true)]
|
||||
[DataRow("v0.1.0.0.1.0.0.0.0", "v0.1.0.0.1", true)]
|
||||
[DataRow("v0.1.0", "v0.1", true)]
|
||||
[DataRow("0.1.0", "0.1", true)]
|
||||
[DataRow("v0.1.0.0.0", "v0.1", true)]
|
||||
[DataRow("0.1.0.0.0", "0.1", true)]
|
||||
[DataRow("v0", "v0", true)]
|
||||
[DataRow("0", "0", true)]
|
||||
[DataRow("v0.1", "v0.1", true)]
|
||||
[DataRow("0.1-release", "0.1-release", true)]
|
||||
[DataRow("v0.1-release", "v0.1-release", true)]
|
||||
[DataRow("v0.1.0.0", "v0.1.0.0.1", false)]
|
||||
[DataRow("v0.1.0.0.1", "v0.1.0.0", false)]
|
||||
[DataRow("v0.9.8.9", "v0.9.8.10", false)]
|
||||
[DataRow("0.1-release", "0.2-release", false)]
|
||||
[DataRow("v1.1-release", "v0.1-release", false)]
|
||||
[TestMethod]
|
||||
public void Equals(string version, string version2, bool result)
|
||||
{
|
||||
var parsedVersion1 = Version.Parse(version);
|
||||
var parsedVersion2 = Version.Parse(version2);
|
||||
|
||||
parsedVersion1.Equals(parsedVersion2).Should().Be(result);
|
||||
}
|
||||
|
||||
[DataRow("v0.1.0.0.1", "v0.1.0.0.1", 0)]
|
||||
[DataRow("v0.1.0.0.1.0.0.0.0", "v0.1.0.0.1", 0)]
|
||||
[DataRow("v0.1.0", "v0.1", 0)]
|
||||
[DataRow("0.1.0", "0.1", 0)]
|
||||
[DataRow("v0.1.0.0.0", "v0.1", 0)]
|
||||
[DataRow("0.1.0.0.0", "0.1", 0)]
|
||||
[DataRow("v0", "v0", 0)]
|
||||
[DataRow("0", "0", 0)]
|
||||
[DataRow("v0.1", "v0.1", 0)]
|
||||
[DataRow("0.1-release", "0.1-release", 0)]
|
||||
[DataRow("v0.1-release", "v0.1-release", 0)]
|
||||
[DataRow("v0.1.0.0", "v0.1.0.0.1", -1)]
|
||||
[DataRow("v0.1.0.0.1", "v0.1.0.0", 1)]
|
||||
[DataRow("v0.9.8.9", "v0.9.8.10", -1)]
|
||||
[DataRow("v0.9.8.10", "v0.9.8.9", 1)]
|
||||
[DataRow("0.1-release", "0.2-release", -1)]
|
||||
[DataRow("v1.1-release", "v0.1-release", 1)]
|
||||
[TestMethod]
|
||||
public void CompareTo(string version, string version2, int comparisonResult)
|
||||
{
|
||||
var parsedVersion1 = Version.Parse(version);
|
||||
var parsedVersion2 = Version.Parse(version2);
|
||||
|
||||
parsedVersion1.CompareTo(parsedVersion2).Should().Be(comparisonResult);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using Daybreak.Services.ApplicationArguments;
|
||||
using Daybreak.Tests.Services.Models;
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using NSubstitute;
|
||||
using Slim;
|
||||
|
||||
namespace Daybreak.Tests.Services;
|
||||
|
||||
[TestClass]
|
||||
public class ApplicationArgumentServiceTests
|
||||
{
|
||||
private readonly ServiceManager serviceManager = new();
|
||||
private readonly ApplicationArgumentService applicationArgumentService;
|
||||
|
||||
public ApplicationArgumentServiceTests()
|
||||
{
|
||||
this.applicationArgumentService = new ApplicationArgumentService(this.serviceManager, Substitute.For<ILogger<ApplicationArgumentService>>());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void HandleArguments_ExpectedArguments_HandlesCorrectly()
|
||||
{
|
||||
this.serviceManager.RegisterSingleton<TestArgumentHandler>();
|
||||
this.serviceManager.RegisterSingleton<TestArgumentHandler2>();
|
||||
|
||||
this.applicationArgumentService.HandleArguments("-r so me arg -c uments he re and there".Split(" "));
|
||||
|
||||
this.serviceManager.GetRequiredService<TestArgumentHandler>().Called.Should().BeTrue();
|
||||
this.serviceManager.GetRequiredService<TestArgumentHandler2>().Called.Should().BeTrue();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void HandleArguments_NotEnoughArguments_DoesNotCallHandlers()
|
||||
{
|
||||
this.serviceManager.RegisterScoped<TestArgumentHandler>();
|
||||
this.serviceManager.RegisterScoped<TestArgumentHandler2>();
|
||||
|
||||
this.applicationArgumentService.HandleArguments("-r so me arg -c uments he re".Split(" "));
|
||||
|
||||
this.serviceManager.GetRequiredService<TestArgumentHandler>().Called.Should().BeTrue();
|
||||
this.serviceManager.GetRequiredService<TestArgumentHandler2>().Called.Should().BeFalse();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RegisterHandler_RegistersHandler()
|
||||
{
|
||||
this.applicationArgumentService.RegisterArgumentHandler<TestArgumentHandler>();
|
||||
|
||||
var action = this.serviceManager.GetRequiredService<TestArgumentHandler>;
|
||||
|
||||
action.Should().NotThrow();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,540 @@
|
||||
using Daybreak.Models.Builds;
|
||||
using Daybreak.Models.Guildwars;
|
||||
using Daybreak.Services.BuildTemplates;
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using NSubstitute;
|
||||
|
||||
namespace Daybreak.Tests.Services;
|
||||
|
||||
[TestClass]
|
||||
public class BuildTemplateManagerTests
|
||||
{
|
||||
private const string EncodedSingleTemplate = "OwBk0texXNu0Dj/z+TDzBj+TN4AE";
|
||||
private const string EncodedTeamTemplate = "OQJUAMxOEMLnw0nDXQGY6aw2B OQNCA8wDP9B8DyzmOUi1veC OggjYxXTIPWbp5krZfxEAAAoD OwUTM4HDn5gc9TJSh6xddmETA";
|
||||
private IBuildTemplateManager buildTemplateManager;
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
this.buildTemplateManager = new BuildTemplateManager(Substitute.For<ILogger<BuildTemplateManager>>());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestSingleDecode()
|
||||
{
|
||||
var build = this.buildTemplateManager.DecodeTemplate(EncodedSingleTemplate);
|
||||
var singleBuildEntry = build.As<SingleBuildEntry>();
|
||||
singleBuildEntry.Should().NotBeNull();
|
||||
singleBuildEntry.Primary.Should().Be(Profession.Assassin);
|
||||
singleBuildEntry.Secondary.Should().Be(Profession.None);
|
||||
singleBuildEntry.Attributes.Count.Should().Be(4);
|
||||
singleBuildEntry.Attributes[1].Attribute.Should().Be(Attribute.DaggerMastery);
|
||||
singleBuildEntry.Attributes[1].Points.Should().Be(11);
|
||||
singleBuildEntry.Attributes[2].Attribute.Should().Be(Attribute.DeadlyArts);
|
||||
singleBuildEntry.Attributes[2].Points.Should().Be(1);
|
||||
singleBuildEntry.Attributes[3].Attribute.Should().Be(Attribute.ShadowArts);
|
||||
singleBuildEntry.Attributes[3].Points.Should().Be(5);
|
||||
singleBuildEntry.Attributes[0].Attribute.Should().Be(Attribute.CriticalStrikes);
|
||||
singleBuildEntry.Attributes[0].Points.Should().Be(11);
|
||||
singleBuildEntry.Skills.Count.Should().Be(8);
|
||||
singleBuildEntry.Skills[0].Should().Be(Skill.UnsuspectingStrike);
|
||||
singleBuildEntry.Skills[1].Should().Be(Skill.WildStrike);
|
||||
singleBuildEntry.Skills[2].Should().Be(Skill.CriticalStrike);
|
||||
singleBuildEntry.Skills[3].Should().Be(Skill.MoebiusStrike);
|
||||
singleBuildEntry.Skills[4].Should().Be(Skill.DeathBlossom);
|
||||
singleBuildEntry.Skills[5].Should().Be(Skill.CriticalEye);
|
||||
singleBuildEntry.Skills[6].Should().Be(Skill.CriticalAgility);
|
||||
singleBuildEntry.Skills[7].Should().Be(Skill.CriticalDefenses);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestTeamDecode()
|
||||
{
|
||||
var build = this.buildTemplateManager.DecodeTemplate(EncodedTeamTemplate);
|
||||
var teamBuildEntry = build.As<TeamBuildEntry>();
|
||||
teamBuildEntry.Should().NotBeNull();
|
||||
teamBuildEntry.Builds.Should().HaveCount(4);
|
||||
|
||||
var firstBuild = teamBuildEntry.Builds[0];
|
||||
firstBuild.Primary.Should().Be(Profession.Mesmer);
|
||||
firstBuild.Secondary.Should().Be(Profession.Ranger);
|
||||
firstBuild.Attributes.Should().BeEquivalentTo(
|
||||
[
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.FastCasting,
|
||||
Points = 6
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.DominationMagic,
|
||||
Points = 11
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.IllusionMagic,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.InspirationMagic,
|
||||
Points = 2
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.BeastMastery,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.Marksmanship,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.WildernessSurvival,
|
||||
Points = 12
|
||||
},
|
||||
]);
|
||||
firstBuild.Skills.Should().BeEquivalentTo(
|
||||
[
|
||||
Skill.EnergySurge,
|
||||
Skill.Mistrust,
|
||||
Skill.CryofFrustration,
|
||||
Skill.PowerSpike,
|
||||
Skill.PowerDrain,
|
||||
Skill.UnnaturalSignet,
|
||||
Skill.Empathy,
|
||||
Skill.QuickeningZephyr
|
||||
]);
|
||||
|
||||
var secondBuild = teamBuildEntry.Builds[1];
|
||||
secondBuild.Primary.Should().Be(Profession.Mesmer);
|
||||
secondBuild.Secondary.Should().Be(Profession.Monk);
|
||||
secondBuild.Attributes.Should().BeEquivalentTo(
|
||||
[
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.FastCasting,
|
||||
Points = 12
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.DominationMagic,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.IllusionMagic,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.InspirationMagic,
|
||||
Points = 12
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.HealingPrayers,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.SmitingPrayers,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.ProtectionPrayers,
|
||||
Points = 0
|
||||
},
|
||||
]);
|
||||
secondBuild.Skills.Should().BeEquivalentTo(
|
||||
[
|
||||
Skill.SymbolicCelerity,
|
||||
Skill.MantraofInscriptions,
|
||||
Skill.KeystoneSignet,
|
||||
Skill.SignetofClumsiness,
|
||||
Skill.UnnaturalSignet,
|
||||
Skill.BaneSignet,
|
||||
Skill.CastigationSignet,
|
||||
Skill.SignetofRage
|
||||
]);
|
||||
|
||||
var thirdBuild = teamBuildEntry.Builds[2];
|
||||
thirdBuild.Primary.Should().Be(Profession.Ranger);
|
||||
thirdBuild.Secondary.Should().Be(Profession.Ritualist);
|
||||
thirdBuild.Attributes.Should().BeEquivalentTo(
|
||||
[
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.Expertise,
|
||||
Points = 3
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.BeastMastery,
|
||||
Points = 12
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.Marksmanship,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.WildernessSurvival,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.ChannelingMagic,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.Communing,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.RestorationMagic,
|
||||
Points = 12
|
||||
},
|
||||
]);
|
||||
thirdBuild.Skills.Should().BeEquivalentTo(
|
||||
[
|
||||
Skill.XinraesWeapon,
|
||||
Skill.MendBodyandSoul,
|
||||
Skill.SpiritLight,
|
||||
Skill.GhostmirrorLight,
|
||||
Skill.FleshofMyFlesh,
|
||||
Skill.ResurrectionSignet,
|
||||
Skill.NoSkill,
|
||||
Skill.EdgeofExtinction
|
||||
]);
|
||||
|
||||
var fourthBuild = teamBuildEntry.Builds[3];
|
||||
fourthBuild.Primary.Should().Be(Profession.Monk);
|
||||
fourthBuild.Secondary.Should().Be(Profession.Mesmer);
|
||||
fourthBuild.Attributes.Should().BeEquivalentTo(
|
||||
[
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.DivineFavor,
|
||||
Points = 3
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.HealingPrayers,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.SmitingPrayers,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.ProtectionPrayers,
|
||||
Points = 12
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.DominationMagic,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.IllusionMagic,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.InspirationMagic,
|
||||
Points = 12
|
||||
},
|
||||
]);
|
||||
fourthBuild.Skills.Should().BeEquivalentTo(
|
||||
[
|
||||
Skill.ProtectiveBond,
|
||||
Skill.PurifyingVeil,
|
||||
Skill.BlessedSignet,
|
||||
Skill.MantraofRecall,
|
||||
Skill.ProtectiveSpirit,
|
||||
Skill.ShieldofAbsorption,
|
||||
Skill.ReversalofFortune,
|
||||
Skill.Resurrect
|
||||
]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestSingleEncode()
|
||||
{
|
||||
var build = new SingleBuildEntry()
|
||||
{
|
||||
Primary = Profession.Assassin,
|
||||
Secondary = Profession.None,
|
||||
Attributes =
|
||||
[
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.DaggerMastery,
|
||||
Points = 11
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.DeadlyArts,
|
||||
Points = 1
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.ShadowArts,
|
||||
Points = 5
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.CriticalStrikes,
|
||||
Points = 11
|
||||
}
|
||||
],
|
||||
Skills =
|
||||
[
|
||||
Skill.UnsuspectingStrike,
|
||||
Skill.WildStrike,
|
||||
Skill.CriticalStrike,
|
||||
Skill.MoebiusStrike,
|
||||
Skill.DeathBlossom,
|
||||
Skill.CriticalEye,
|
||||
Skill.CriticalAgility,
|
||||
Skill.CriticalDefenses
|
||||
]
|
||||
};
|
||||
|
||||
var encoded = this.buildTemplateManager.EncodeTemplate(build);
|
||||
encoded.Should().Be(EncodedSingleTemplate);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestTeamEncode()
|
||||
{
|
||||
var build = new TeamBuildEntry
|
||||
{
|
||||
Builds = [
|
||||
new SingleBuildEntry
|
||||
{
|
||||
Primary = Profession.Mesmer,
|
||||
Secondary = Profession.Ranger,
|
||||
Attributes = [
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.FastCasting,
|
||||
Points = 6
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.DominationMagic,
|
||||
Points = 11
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.IllusionMagic,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.InspirationMagic,
|
||||
Points = 2
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.BeastMastery,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.Marksmanship,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.WildernessSurvival,
|
||||
Points = 12
|
||||
},
|
||||
],
|
||||
Skills = [
|
||||
Skill.EnergySurge,
|
||||
Skill.Mistrust,
|
||||
Skill.CryofFrustration,
|
||||
Skill.PowerSpike,
|
||||
Skill.PowerDrain,
|
||||
Skill.UnnaturalSignet,
|
||||
Skill.Empathy,
|
||||
Skill.QuickeningZephyr
|
||||
]
|
||||
},
|
||||
new SingleBuildEntry
|
||||
{
|
||||
Primary = Profession.Mesmer,
|
||||
Secondary = Profession.Monk,
|
||||
Attributes = [
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.FastCasting,
|
||||
Points = 12
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.DominationMagic,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.IllusionMagic,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.InspirationMagic,
|
||||
Points = 12
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.HealingPrayers,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.SmitingPrayers,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.ProtectionPrayers,
|
||||
Points = 0
|
||||
},
|
||||
],
|
||||
Skills = [
|
||||
Skill.SymbolicCelerity,
|
||||
Skill.MantraofInscriptions,
|
||||
Skill.KeystoneSignet,
|
||||
Skill.SignetofClumsiness,
|
||||
Skill.UnnaturalSignet,
|
||||
Skill.BaneSignet,
|
||||
Skill.CastigationSignet,
|
||||
Skill.SignetofRage
|
||||
]
|
||||
},
|
||||
new SingleBuildEntry
|
||||
{
|
||||
Primary = Profession.Ranger,
|
||||
Secondary = Profession.Ritualist,
|
||||
Attributes = [
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.Expertise,
|
||||
Points = 3
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.BeastMastery,
|
||||
Points = 12
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.Marksmanship,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.WildernessSurvival,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.ChannelingMagic,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.Communing,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.RestorationMagic,
|
||||
Points = 12
|
||||
},
|
||||
],
|
||||
Skills = [
|
||||
Skill.XinraesWeapon,
|
||||
Skill.MendBodyandSoul,
|
||||
Skill.SpiritLight,
|
||||
Skill.GhostmirrorLight,
|
||||
Skill.FleshofMyFlesh,
|
||||
Skill.ResurrectionSignet,
|
||||
Skill.NoSkill,
|
||||
Skill.EdgeofExtinction
|
||||
]
|
||||
},
|
||||
new SingleBuildEntry
|
||||
{
|
||||
Primary = Profession.Monk,
|
||||
Secondary = Profession.Mesmer,
|
||||
Attributes = [
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.DivineFavor,
|
||||
Points = 3
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.HealingPrayers,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.SmitingPrayers,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.ProtectionPrayers,
|
||||
Points = 12
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.DominationMagic,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.IllusionMagic,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.InspirationMagic,
|
||||
Points = 12
|
||||
},
|
||||
],
|
||||
Skills = [
|
||||
Skill.ProtectiveBond,
|
||||
Skill.PurifyingVeil,
|
||||
Skill.BlessedSignet,
|
||||
Skill.MantraofRecall,
|
||||
Skill.ProtectiveSpirit,
|
||||
Skill.ShieldofAbsorption,
|
||||
Skill.ReversalofFortune,
|
||||
Skill.Resurrect
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var encoded = this.buildTemplateManager.EncodeTemplate(build);
|
||||
encoded.Should().Be(EncodedTeamTemplate);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Daybreak.Services.ApplicationArguments.ArgumentHandling;
|
||||
using FluentAssertions;
|
||||
|
||||
namespace Daybreak.Tests.Services.Models;
|
||||
public sealed class TestArgumentHandler : IArgumentHandler
|
||||
{
|
||||
public string Identifier => "-r";
|
||||
public int ExpectedArgumentCount => 3;
|
||||
public bool Called { get; private set; }
|
||||
|
||||
public void HandleArguments(string[] args)
|
||||
{
|
||||
args.Should().BeEquivalentTo(["so", "me", "arg"]);
|
||||
this.Called = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Daybreak.Services.ApplicationArguments.ArgumentHandling;
|
||||
using FluentAssertions;
|
||||
|
||||
namespace Daybreak.Tests.Services.Models;
|
||||
public sealed class TestArgumentHandler2 : IArgumentHandler
|
||||
{
|
||||
public string Identifier => "-c";
|
||||
public int ExpectedArgumentCount => 5;
|
||||
public bool Called { get; private set; }
|
||||
|
||||
public void HandleArguments(string[] args)
|
||||
{
|
||||
args.Should().BeEquivalentTo(["uments", "he", "re", "and", "there"]);
|
||||
this.Called = true;
|
||||
}
|
||||
}
|
||||
+73
-2
@@ -1,26 +1,97 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.31005.135
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.2.32616.157
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Daybreak", "Daybreak\Daybreak.csproj", "{AA45C2B1-8BD0-466C-9271-699F168905AF}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Daybreak.Tests", "Daybreak.Tests\Daybreak.Tests.csproj", "{C911C1C2-6566-419C-89C7-F802EB3FE709}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Pipelines", "Pipelines", "{067BF93F-E5B2-4E99-886E-039C04F35EAB}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.github\workflows\cd.yaml = .github\workflows\cd.yaml
|
||||
.github\workflows\ci.yaml = .github\workflows\ci.yaml
|
||||
.github\workflows\codeql-analysis.yml = .github\workflows\codeql-analysis.yml
|
||||
.github\dependabot.yml = .github\dependabot.yml
|
||||
.github\workflows\version_check.yaml = .github\workflows\version_check.yaml
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Daybreak.Installer", "Daybreak.Installer\Daybreak.Installer.csproj", "{4E2BB805-135D-4F02-8C53-3D8B6876D323}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripts", "Scripts", "{41AE8C5D-25E1-4B08-8D65-868552421A63}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Scripts\BuildRelease.ps1 = Scripts\BuildRelease.ps1
|
||||
Scripts\CompareVersions.ps1 = Scripts\CompareVersions.ps1
|
||||
Scripts\GetBuildVersion.ps1 = Scripts\GetBuildVersion.ps1
|
||||
Scripts\PushFilesToBlobStorage.ps1 = Scripts\PushFilesToBlobStorage.ps1
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0E30DDA0-2111-4E6C-851E-01DC34124FC2}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.editorconfig = .editorconfig
|
||||
.github\CODEOWNERS = .github\CODEOWNERS
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Daybreak.7ZipExtractor", "Daybreak.7ZipExtractor\Daybreak.7ZipExtractor.csproj", "{CA60F9AC-A496-4DB6-970E-ECE73B051C05}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Debug|x64.Build.0 = Debug|x64
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Debug|x86.Build.0 = Debug|x86
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Release|x64.ActiveCfg = Release|x64
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Release|x64.Build.0 = Release|x64
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Release|x86.ActiveCfg = Release|x86
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Release|x86.Build.0 = Release|x86
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Debug|x64.Build.0 = Debug|x64
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Debug|x86.Build.0 = Debug|x86
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Release|x64.ActiveCfg = Release|x64
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Release|x64.Build.0 = Release|x64
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Release|x86.ActiveCfg = Release|x86
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Release|x86.Build.0 = Release|x86
|
||||
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Debug|x64.ActiveCfg = Debug|x86
|
||||
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Debug|x64.Build.0 = Debug|x86
|
||||
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Debug|x86.Build.0 = Debug|x86
|
||||
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Release|x64.ActiveCfg = Release|x64
|
||||
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Release|x64.Build.0 = Release|x64
|
||||
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Release|x86.ActiveCfg = Release|x86
|
||||
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Release|x86.Build.0 = Release|x86
|
||||
{CA60F9AC-A496-4DB6-970E-ECE73B051C05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CA60F9AC-A496-4DB6-970E-ECE73B051C05}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CA60F9AC-A496-4DB6-970E-ECE73B051C05}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{CA60F9AC-A496-4DB6-970E-ECE73B051C05}.Debug|x64.Build.0 = Debug|x64
|
||||
{CA60F9AC-A496-4DB6-970E-ECE73B051C05}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{CA60F9AC-A496-4DB6-970E-ECE73B051C05}.Debug|x86.Build.0 = Debug|x64
|
||||
{CA60F9AC-A496-4DB6-970E-ECE73B051C05}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CA60F9AC-A496-4DB6-970E-ECE73B051C05}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CA60F9AC-A496-4DB6-970E-ECE73B051C05}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{CA60F9AC-A496-4DB6-970E-ECE73B051C05}.Release|x64.Build.0 = Release|Any CPU
|
||||
{CA60F9AC-A496-4DB6-970E-ECE73B051C05}.Release|x86.ActiveCfg = Release|x64
|
||||
{CA60F9AC-A496-4DB6-970E-ECE73B051C05}.Release|x86.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using Daybreak.Validators;
|
||||
using System;
|
||||
|
||||
namespace Daybreak.Attributes;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public sealed class OptionCustomValidatorAttribute<T> : Attribute
|
||||
where T : IValidator, new()
|
||||
{
|
||||
public IValidator Validator { get; }
|
||||
|
||||
public OptionCustomValidatorAttribute()
|
||||
{
|
||||
this.Validator = Activator.CreateInstance<T>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using System;
|
||||
|
||||
namespace Daybreak.Attributes;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public sealed class OptionIgnoreAttribute : Attribute
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
|
||||
namespace Daybreak.Attributes;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public sealed class OptionNameAttribute : Attribute
|
||||
{
|
||||
public string Name { get; init; } = string.Empty;
|
||||
public string Description { get; init; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
|
||||
namespace Daybreak.Attributes;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public sealed class OptionRangeAttribute<T> : Attribute
|
||||
where T : IComparable<T>
|
||||
{
|
||||
public T MinValue { get; init; } = default!;
|
||||
public T MaxValue { get; init; } = default!;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Attributes;
|
||||
|
||||
/// <summary>
|
||||
/// Mark a custom view that is supposed to set the value of the option.
|
||||
/// In the option view, a button will be displayed that will redirect to the custom view.
|
||||
/// The custom view must be registered in the <see cref="Services.Navigation.IViewManager"/>
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of view. Has to be registered in the <see cref="Services.Navigation.IViewManager"./></typeparam>
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public sealed class OptionSetterView<T> : Attribute
|
||||
where T : UserControl
|
||||
{
|
||||
public string Action { get; set; } = "Set";
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using System;
|
||||
|
||||
namespace Daybreak.Attributes;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public sealed class OptionSynchronizationIgnoreAttribute : Attribute
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using System;
|
||||
|
||||
namespace Daybreak.Attributes;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public sealed class OptionsIgnoreAttribute : Attribute
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using System;
|
||||
|
||||
namespace Daybreak.Attributes;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public sealed class OptionsNameAttribute : Attribute
|
||||
{
|
||||
public string? Name { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using System;
|
||||
|
||||
namespace Daybreak.Attributes;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public sealed class OptionsSynchronizationIgnoreAttribute : Attribute
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Behaviors;
|
||||
internal sealed class LayoutFreezeDecorator : Decorator
|
||||
{
|
||||
public bool IsLayoutFrozen { get; set; }
|
||||
|
||||
protected override Size MeasureOverride(Size constraint)
|
||||
{
|
||||
if (this.IsLayoutFrozen)
|
||||
{
|
||||
return new Size(0, 0);
|
||||
}
|
||||
|
||||
return base.MeasureOverride(constraint);
|
||||
}
|
||||
|
||||
protected override Size ArrangeOverride(Size arrangeSize)
|
||||
{
|
||||
if (this.IsLayoutFrozen)
|
||||
{
|
||||
return arrangeSize;
|
||||
}
|
||||
|
||||
return base.ArrangeOverride(arrangeSize);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
using Microsoft.Xaml.Behaviors;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Behaviors;
|
||||
public sealed class RowAutoMargin : Behavior<Grid>
|
||||
{
|
||||
private const string GeneratedRowsTag = "Definition generated by RowAutoMargin.cs";
|
||||
public double Margin { get; set; } = 10;
|
||||
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
|
||||
/*
|
||||
* We need to trigger the behavior only after the object is fully loaded and rows are generated
|
||||
*/
|
||||
this.AssociatedObject.Loaded += this.AssociatedObject_Loaded;
|
||||
}
|
||||
|
||||
// TODO #367: Super hacky code below. To be reworked
|
||||
public void RecalculateRows()
|
||||
{
|
||||
/*
|
||||
* Tag each child with the desired row. Skip children already tagged
|
||||
*/
|
||||
foreach (var child in this.AssociatedObject.Children.OfType<FrameworkElement>())
|
||||
{
|
||||
if (child.Tag is int desiredRow)
|
||||
{
|
||||
Grid.SetRow(child, desiredRow);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (child.Tag is not null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
child.Tag = Grid.GetRow(child);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove previously generated rows
|
||||
*/
|
||||
for (var i = 0; i < this.AssociatedObject.RowDefinitions.Count; i++)
|
||||
{
|
||||
if (this.AssociatedObject.RowDefinitions[i].Tag is string stringTag &&
|
||||
stringTag == GeneratedRowsTag)
|
||||
{
|
||||
this.AssociatedObject.RowDefinitions.RemoveAt(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The idea is to generate some rows with Margin set as height when we detect that there are more than one rows.
|
||||
* First we need to detect if there are more rows.
|
||||
*/
|
||||
if (this.AssociatedObject.RowDefinitions
|
||||
.Where(r => r.Tag is not string stringTag || stringTag != GeneratedRowsTag)
|
||||
.Where(r => r.Height.Value > 0)
|
||||
.Count() <= 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate new rows with height set to Margin
|
||||
*/
|
||||
var addedRows = 0;
|
||||
for (var i = 0; i < this.AssociatedObject.RowDefinitions.Count - 1; i++)
|
||||
{
|
||||
var rowDefinition = this.AssociatedObject.RowDefinitions[i];
|
||||
if (rowDefinition.Height.Value > 0 &&
|
||||
(rowDefinition.Tag is not string tagString ||
|
||||
tagString is not GeneratedRowsTag))
|
||||
{
|
||||
this.AssociatedObject.RowDefinitions.Insert(i + 1,
|
||||
new RowDefinition
|
||||
{
|
||||
Height = new GridLength(this.Margin, GridUnitType.Pixel),
|
||||
Tag = GeneratedRowsTag
|
||||
});
|
||||
foreach (var child in this.AssociatedObject.Children.OfType<FrameworkElement>())
|
||||
{
|
||||
if (child.Tag is int desiredRow &&
|
||||
desiredRow > i - addedRows)
|
||||
{
|
||||
Grid.SetRow(child, Grid.GetRow(child) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
addedRows++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.RecalculateRows();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
using Microsoft.Xaml.Behaviors;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Daybreak.Behaviors;
|
||||
|
||||
public class ScaleFontWithSize : Behavior<TextBlock>
|
||||
{
|
||||
public static readonly DependencyProperty MaxFontSizeProperty = DependencyProperty.Register("MaxFontSize", typeof(double), typeof(ScaleFontWithSize), new PropertyMetadata(12d));
|
||||
|
||||
public double MaxFontSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return (double)this.GetValue(MaxFontSizeProperty);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.SetValue(MaxFontSizeProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
this.AssociatedObject.SizeChanged += (_, __) => this.CalculateFontSize();
|
||||
DependencyPropertyDescriptor.FromProperty(
|
||||
TextBlock.TextProperty, typeof(TextBlock)).AddValueChanged(this.AssociatedObject, (_, __) => this.CalculateFontSize());
|
||||
DependencyPropertyDescriptor.FromProperty(
|
||||
TextBlock.FontSizeProperty, typeof(TextBlock)).AddValueChanged(this.AssociatedObject, (_, __) => this.CalculateFontSize());
|
||||
}
|
||||
|
||||
private void CalculateFontSize()
|
||||
{
|
||||
var textMeasurement = this.MeasureText(this.AssociatedObject.FontSize);
|
||||
var maximumTextMeasurement = this.MeasureText(this.MaxFontSize);
|
||||
var desiredWidthFontSize = this.MaxFontSize;
|
||||
var desiredHeightFontSize = this.MaxFontSize;
|
||||
|
||||
if (Math.Round(textMeasurement.Height) != Math.Round(this.AssociatedObject.ActualHeight))
|
||||
{
|
||||
|
||||
var scale = this.AssociatedObject.ActualHeight / maximumTextMeasurement.Height;
|
||||
desiredHeightFontSize = (this.MaxFontSize * scale) - 1;
|
||||
desiredHeightFontSize = desiredHeightFontSize <= this.MaxFontSize ? desiredHeightFontSize : this.MaxFontSize;
|
||||
}
|
||||
|
||||
if (Math.Round(textMeasurement.Width) != Math.Round(this.AssociatedObject.ActualWidth))
|
||||
{
|
||||
var scale = this.AssociatedObject.ActualWidth / maximumTextMeasurement.Width;
|
||||
desiredWidthFontSize = (this.MaxFontSize * scale) - 1;
|
||||
desiredWidthFontSize = desiredWidthFontSize <= this.MaxFontSize ? desiredWidthFontSize : this.MaxFontSize;
|
||||
|
||||
}
|
||||
|
||||
var desiredFontSize = Math.Min(desiredHeightFontSize, desiredWidthFontSize);
|
||||
|
||||
if ((int)desiredFontSize != (int)this.AssociatedObject.FontSize && desiredFontSize > 0)
|
||||
{
|
||||
this.AssociatedObject.FontSize = desiredFontSize;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private Size MeasureText(double fontSize)
|
||||
{
|
||||
var formattedText = new FormattedText(this.AssociatedObject.Text, CultureInfo.CurrentUICulture,
|
||||
FlowDirection.LeftToRight,
|
||||
new Typeface(this.AssociatedObject.FontFamily, this.AssociatedObject.FontStyle, this.AssociatedObject.FontWeight, this.AssociatedObject.FontStretch),
|
||||
fontSize, Brushes.Black, VisualTreeHelper.GetDpi(this.AssociatedObject).PixelsPerDip);
|
||||
|
||||
return new Size(formattedText.Width, formattedText.Height);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using Microsoft.Xaml.Behaviors;
|
||||
using System;
|
||||
using System.Extensions;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Behaviors;
|
||||
|
||||
public class ScrollIntoView : Behavior<ListView>
|
||||
{
|
||||
/// <summary>
|
||||
/// When Beahvior is attached
|
||||
/// </summary>
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
this.AssociatedObject.SelectionChanged += this.AssociatedObject_SelectionChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On Selection Changed
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void AssociatedObject_SelectionChanged(object sender,
|
||||
SelectionChangedEventArgs e)
|
||||
{
|
||||
if (sender is ListView)
|
||||
{
|
||||
var listView = sender.As<ListView>()!;
|
||||
if (listView.SelectedItem != null)
|
||||
{
|
||||
listView.Dispatcher.BeginInvoke(
|
||||
(Action)(() =>
|
||||
{
|
||||
listView.UpdateLayout();
|
||||
if (listView.SelectedItem !=
|
||||
null)
|
||||
listView.ScrollIntoView(
|
||||
listView.SelectedItem);
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// When behavior is detached
|
||||
/// </summary>
|
||||
protected override void OnDetaching()
|
||||
{
|
||||
base.OnDetaching();
|
||||
this.AssociatedObject.SelectionChanged -=
|
||||
this.AssociatedObject_SelectionChanged;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Daybreak.Configuration
|
||||
{
|
||||
public sealed class ApplicationConfiguration
|
||||
{
|
||||
[JsonProperty("GamePath")]
|
||||
public string GamePath { get; set; }
|
||||
[JsonProperty("CharacterName")]
|
||||
public string CharacterName { get; set; }
|
||||
[JsonProperty("LeftBrowserDefault")]
|
||||
public string LeftBrowserDefault { get; set; }
|
||||
[JsonProperty("RightBrowserDefault")]
|
||||
public string RightBrowserDefault { get; set; }
|
||||
[JsonProperty("ProtectedUsername")]
|
||||
public string ProtectedUsername { get; set; }
|
||||
[JsonProperty("ProtectedPassword")]
|
||||
public string ProtectedPassword { get; set; }
|
||||
[JsonProperty("AddressBarReadonly")]
|
||||
public bool AddressBarReadonly { get; set; } = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Daybreak.Configuration.FocusView;
|
||||
|
||||
public enum ExperienceDisplay
|
||||
{
|
||||
TotalCurretAndTotalMax,
|
||||
CurrentLevelCurrentAndCurrentLevelMax,
|
||||
RemainingUntilNextLevel,
|
||||
Percentage
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Daybreak.Configuration.FocusView;
|
||||
|
||||
public enum PointsDisplay
|
||||
{
|
||||
CurrentAndMax,
|
||||
Remaining,
|
||||
Percentage
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using Daybreak.Attributes;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Ascalon Trade Chat")]
|
||||
[OptionsIgnore]
|
||||
[OptionsSynchronizationIgnore]
|
||||
public sealed class AscalonTradeChatOptions : ITradeChatOptions
|
||||
{
|
||||
public string HttpsUri { get; set; } = "https://ascalon.gwtoolbox.com/";
|
||||
|
||||
public string WssUri { get; set; } = "wss://ascalon.gwtoolbox.com/";
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Daybreak.Attributes;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Background Provider")]
|
||||
internal sealed class BackgroundProviderOptions
|
||||
{
|
||||
[OptionName(Name = "Bloogum Client Enabled", Description = "When enabled, Background Provider will make use of Bloogum to get background images")]
|
||||
[JsonProperty(nameof(BloogumEnabled))]
|
||||
public bool BloogumEnabled { get; set; } = true;
|
||||
|
||||
[OptionName(Name = "Local Screenshots Enabled", Description = "When enabled, Background Provider will make use of the local Guild Wars screenshots to get background images")]
|
||||
[JsonProperty(nameof(LocalScreenshotsEnabled))]
|
||||
public bool LocalScreenshotsEnabled { get; set; } = true;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using Daybreak.Attributes;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Browser")]
|
||||
public sealed class BrowserOptions
|
||||
{
|
||||
[JsonProperty(nameof(Enabled))]
|
||||
[OptionName(Name = "Enabled", Description = "If true, the browser component will be displayed")]
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
[JsonProperty(nameof(AddressBarReadonly))]
|
||||
[OptionName(Name = "Read-only Address Bar", Description = "If true, the browser component will force the address bar to be read-only")]
|
||||
public bool AddressBarReadonly { get; set; } = true;
|
||||
|
||||
[JsonProperty(nameof(DynamicBuildLoading))]
|
||||
[OptionName(Name = "Dynamic Build Loading", Description = "If true, the browser will dynamically parse build templates and prompt the user to load them")]
|
||||
public bool DynamicBuildLoading { get; set; } = true;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using Daybreak.Attributes;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Synchronization")]
|
||||
[OptionsIgnore]
|
||||
[OptionsSynchronizationIgnore]
|
||||
internal sealed class SynchronizationOptions
|
||||
{
|
||||
[JsonProperty(nameof(ProtectedGraphAccessToken))]
|
||||
public string? ProtectedGraphAccessToken { get; set; }
|
||||
[JsonProperty(nameof(ProtectedGraphRefreshToken))]
|
||||
public string? ProtectedGraphRefreshToken { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using Daybreak.Attributes;
|
||||
using Daybreak.Models;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsIgnore]
|
||||
[OptionsName(Name = "Credentials")]
|
||||
internal sealed class CredentialManagerOptions
|
||||
{
|
||||
[JsonProperty(nameof(ProtectedLoginCredentials))]
|
||||
public List<ProtectedLoginCredentials> ProtectedLoginCredentials { get; set; } = [];
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Daybreak.Attributes;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
[OptionsName(Name = "DSOAL")]
|
||||
internal sealed class DSOALOptions
|
||||
{
|
||||
[JsonProperty(nameof(Path))]
|
||||
[OptionName(Name = "Path", Description = "The path to the DSOAL installation")]
|
||||
[OptionSynchronizationIgnore]
|
||||
public string? Path { get; set; }
|
||||
|
||||
[JsonProperty(nameof(Enabled))]
|
||||
[OptionName(Name = "Enabled", Description = "If true, the launcher will also launch DSOAL when launching GuildWars")]
|
||||
public bool Enabled { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Daybreak.Attributes;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "DirectSong")]
|
||||
internal sealed class DirectSongOptions
|
||||
{
|
||||
[JsonProperty(nameof(Path))]
|
||||
[OptionName(Name = "Path", Description = "Folder that contains the DirectSong files")]
|
||||
[OptionSynchronizationIgnore]
|
||||
public string Path { get; set; } = string.Empty;
|
||||
|
||||
[JsonProperty(nameof(Enabled))]
|
||||
[OptionName(Name = "Enabled", Description = "If true, Daybreak will setup DirectSong when launching Guild Wars")]
|
||||
public bool Enabled { get; set; } = false;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using Daybreak.Attributes;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Event Notifier")]
|
||||
internal sealed class EventNotifierOptions
|
||||
{
|
||||
[OptionName(Name = "Enabled", Description = "If set to true, Daybreak will notify the user of any event on startup")]
|
||||
public bool Enabled { get; set; } = true;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using Daybreak.Attributes;
|
||||
using Daybreak.Configuration.FocusView;
|
||||
using Daybreak.Models.Browser;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Focus View")]
|
||||
public sealed class FocusViewOptions
|
||||
{
|
||||
[JsonProperty(nameof(Enabled))]
|
||||
[OptionName(Name = "Enabled", Description = "If true, the focus view is enabled, showing live information from the game")]
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
[JsonProperty(nameof(ExperienceDisplay))]
|
||||
[OptionName(Name = "Experience Display Mode", Description = "Sets how should the experience display show the information")]
|
||||
public ExperienceDisplay ExperienceDisplay { get; set; }
|
||||
|
||||
[JsonProperty(nameof(KurzickPointsDisplay))]
|
||||
[OptionName(Name = "Kurzick Points Display Mode", Description = "Sets how should the kurzick points display show the information")]
|
||||
public PointsDisplay KurzickPointsDisplay { get; set; }
|
||||
|
||||
[JsonProperty(nameof(LuxonPointsDisplay))]
|
||||
[OptionName(Name = "Luxon Points Display Mode", Description = "Sets how should the luxon points display show the information")]
|
||||
public PointsDisplay LuxonPointsDisplay { get; set; }
|
||||
|
||||
[JsonProperty(nameof(BalthazarPointsDisplay))]
|
||||
[OptionName(Name = "Balthazar Points Display Mode", Description = "Sets how should the balthazar points display show the information")]
|
||||
public PointsDisplay BalthazarPointsDisplay { get; set; }
|
||||
|
||||
[JsonProperty(nameof(ImperialPointsDisplay))]
|
||||
[OptionName(Name = "Imperial Points Display Mode", Description = "Sets how should the imperial points display show the information")]
|
||||
public PointsDisplay ImperialPointsDisplay { get; set; }
|
||||
|
||||
[JsonProperty(nameof(VanquishingDisplay))]
|
||||
[OptionName(Name = "Vanquishing Display Mode", Description = "Sets how should the vanquishing display show the information")]
|
||||
public PointsDisplay VanquishingDisplay { get; set; }
|
||||
|
||||
[JsonProperty(nameof(HealthDisplay))]
|
||||
[OptionName(Name = "Health Display Mode", Description = "Sets how should the health display show the information")]
|
||||
public PointsDisplay HealthDisplay { get; set; }
|
||||
|
||||
[JsonProperty(nameof(EnergyDisplay))]
|
||||
[OptionName(Name = "Energy Display Mode", Description = "Sets how should the energy display show the information")]
|
||||
public PointsDisplay EnergyDisplay { get; set; }
|
||||
|
||||
[JsonProperty(nameof(BrowserHistory))]
|
||||
[OptionIgnore]
|
||||
public BrowserHistory BrowserHistory { get; set; } = new();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using Daybreak.Attributes;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
[OptionsIgnore]
|
||||
[OptionsSynchronizationIgnore]
|
||||
internal sealed class GuildwarsExecutableOptions
|
||||
{
|
||||
[JsonProperty(nameof(ExecutablePaths))]
|
||||
public List<string> ExecutablePaths { get; set; } = [];
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
public interface ITradeChatOptions
|
||||
{
|
||||
string HttpsUri { get; set; }
|
||||
|
||||
string WssUri { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using Daybreak.Attributes;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Memory Cache")]
|
||||
internal sealed class ImageCacheOptions
|
||||
{
|
||||
[OptionName(Name = "Image Cache Limit", Description = "The maximum number of MBs that will be used to cache images in memory")]
|
||||
[OptionRange<double>(MinValue = 0d, MaxValue = 1000d)]
|
||||
public double MemoryImageCacheLimit { get; set; } = 100;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using Daybreak.Attributes;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Kamadan Trade Chat")]
|
||||
[OptionsIgnore]
|
||||
[OptionsSynchronizationIgnore]
|
||||
public sealed class KamadanTradeChatOptions : ITradeChatOptions
|
||||
{
|
||||
public string HttpsUri { get; set; } = "https://kamadan.gwtoolbox.com/";
|
||||
|
||||
public string WssUri { get; set; } = "wss://kamadan.gwtoolbox.com/";
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using Daybreak.Attributes;
|
||||
using Daybreak.Models.LaunchConfigurations;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsIgnore]
|
||||
[OptionsSynchronizationIgnore]
|
||||
internal sealed class LaunchConfigurationServiceOptions
|
||||
{
|
||||
[JsonProperty(nameof(LaunchConfigurations))]
|
||||
public List<LaunchConfiguration> LaunchConfigurations { get; set; } = [];
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
using Daybreak.Attributes;
|
||||
using Daybreak.Views;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Launcher")]
|
||||
public sealed class LauncherOptions
|
||||
{
|
||||
[JsonProperty(nameof(DynamicBackgrounds))]
|
||||
[OptionName(Name = "Dyamic Backgrounds", Description = "If enabled, Daybreak will periodically change the background image. Otherwise, Daybreak will show a plain background")]
|
||||
[OptionSynchronizationIgnore]
|
||||
public bool DynamicBackgrounds { get; set; } = true;
|
||||
|
||||
[JsonProperty(nameof(SetGuildwarsWindowSizeOnLaunch))]
|
||||
[OptionName(Name = "Set GuildWars Window Size On Launch", Description = "Sets the GuildWars window size and position on launch")]
|
||||
[OptionSynchronizationIgnore]
|
||||
public bool SetGuildwarsWindowSizeOnLaunch { get; set; }
|
||||
|
||||
[JsonProperty(nameof(DesiredGuildwarsScreen))]
|
||||
[OptionName(Name = "Desired GuildWars Screen", Description = "Sets the screen on which the GuildWars window will be placed")]
|
||||
[OptionSetterView<ScreenChoiceView>(Action = "Screen Selector")]
|
||||
[OptionSynchronizationIgnore]
|
||||
public int DesiredGuildwarsScreen { get; set; }
|
||||
|
||||
[JsonProperty(nameof(LaunchGuildwarsAsCurrentUser))]
|
||||
[OptionName(Name = "Launch GuildWars As Current User", Description = "If true, will attempt to launch GuildWars as the current user. Otherwise will attempt to launch as system user")]
|
||||
public bool LaunchGuildwarsAsCurrentUser { get; set; } = true;
|
||||
|
||||
[JsonProperty(nameof(ShortcutLocation))]
|
||||
[OptionName(Name = "Shortcut Location", Description = "Location where the shortcut will be placed")]
|
||||
[OptionSynchronizationIgnore]
|
||||
public string? ShortcutLocation { get; set; } = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
|
||||
|
||||
[JsonProperty(nameof(PlaceShortcut))]
|
||||
[OptionName(Name = "Shortcut Placed", Description = "If true, the shortcut will be placed. If false, the shortcut will be deleted")]
|
||||
public bool PlaceShortcut { get; set; }
|
||||
|
||||
[JsonProperty(nameof(AutoCheckUpdate))]
|
||||
[OptionName(Name = "Auto-Check For Updates", Description = "Automatically check for updates")]
|
||||
public bool AutoCheckUpdate { get; set; } = true;
|
||||
|
||||
[JsonProperty(nameof(MultiLaunchSupport))]
|
||||
[OptionName(Name = "Multi-Launch Support", Description = "If true, the launcher will support multiple executables being launched at the same time")]
|
||||
public bool MultiLaunchSupport { get; set; }
|
||||
|
||||
[JsonProperty(nameof(DownloadIcons))]
|
||||
[OptionName(Name = "Download Icons", Description = "If true, the launcher will download icons that are not found in the local cache")]
|
||||
public bool DownloadIcons { get; set; } = true;
|
||||
|
||||
[JsonProperty(nameof(ModStartupTimeout))]
|
||||
[OptionName(Name = "Mod Startup Timeout", Description = "Amount of seconds that Daybreak will wait for each mod to start-up before cancelling the tasks")]
|
||||
[OptionRange<double>(MinValue = 30, MaxValue = 300)]
|
||||
public double ModStartupTimeout { get; set; } = 30;
|
||||
|
||||
[JsonProperty(nameof(PersistentLogging))]
|
||||
[OptionName(Name = "Persistent Logging", Description = "If true, the launcher will save logs in the local database. Otherwise, the launcher will only keep logs in a memory cache")]
|
||||
public bool PersistentLogging { get; set; } = false;
|
||||
|
||||
[JsonProperty(nameof(BetaUpdate))]
|
||||
[OptionName(Name = "Beta Update", Description = "If true, the launcher will use the new update procedure")]
|
||||
public bool BetaUpdate { get; set; } = true;
|
||||
|
||||
[JsonProperty(nameof(AutoBackupSettings))]
|
||||
[OptionName(Name = "Auto Backup Settings", Description = "If true, the launcher will attempt to backup settings periodically")]
|
||||
public bool AutoBackupSettings { get; set; } = false;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Daybreak.Attributes;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Memory Reader")]
|
||||
internal sealed class MemoryReaderOptions
|
||||
{
|
||||
[JsonProperty(nameof(MemoryReaderFrequency))]
|
||||
[OptionRange<double>(MinValue = 0, MaxValue = 1000)]
|
||||
[OptionName(Name = "Memory Reader Frequency", Description = "Measured in ms. Sets how often should the launcher polls information from the game. Actual frequency is capped by the memory reading speed")]
|
||||
public double MemoryReaderFrequency { get; set; } = 0;
|
||||
|
||||
[JsonProperty(nameof(AllowWhispers))]
|
||||
[OptionName(Name = "Allow Whispers", Description = "If enabled, Daybreak will be allowed to send whispers to the player. Mainly used in notifications")]
|
||||
public bool AllowWhispers { get; set; } = true;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Daybreak.Attributes;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsIgnore]
|
||||
[OptionsName(Name = "Minimap Window")]
|
||||
[OptionsSynchronizationIgnore]
|
||||
public sealed class MinimapWindowOptions
|
||||
{
|
||||
public bool Pinned { get; set; }
|
||||
public double X { get; set; }
|
||||
public double Y { get; set; }
|
||||
public double Width { get; set; }
|
||||
public double Height { get; set; }
|
||||
public double DpiX { get; set; }
|
||||
public double DpiY { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using Daybreak.Attributes;
|
||||
using Daybreak.Services.Plugins.Models;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsIgnore]
|
||||
[OptionsSynchronizationIgnore]
|
||||
internal sealed class PluginsServiceOptions
|
||||
{
|
||||
public List<PluginEntry> EnabledPlugins { get; set; } = [];
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Daybreak.Attributes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Price History")]
|
||||
[OptionsIgnore]
|
||||
[OptionsSynchronizationIgnore]
|
||||
internal sealed class PriceHistoryOptions
|
||||
{
|
||||
public string HttpsUri { get; set; } = "https://kamadan.gwtoolbox.com/";
|
||||
|
||||
public TimeSpan UpdateInterval { get; set; } = TimeSpan.FromHours(1);
|
||||
|
||||
public Dictionary<string, DateTime> PricingHistoryMetadata { get; set; } = [];
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Daybreak.Attributes;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "ReShade")]
|
||||
internal sealed class ReShadeOptions
|
||||
{
|
||||
[JsonProperty(nameof(Enabled))]
|
||||
[OptionName(Name = "Enabled", Description = "If true, Daybreak will attempt to inject ReShade into the starting Guild Wars executable")]
|
||||
public bool Enabled { get; set; } = false;
|
||||
|
||||
[JsonProperty(nameof(AutoUpdate))]
|
||||
[OptionName(Name = "Auto-update", Description = "If true, Daybreak will periodically check ReShade for updates")]
|
||||
public bool AutoUpdate { get; set; } = true;
|
||||
|
||||
[OptionIgnore]
|
||||
public string InstalledVersion { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Daybreak.Attributes;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Screen Manager")]
|
||||
[OptionsIgnore]
|
||||
[OptionsSynchronizationIgnore]
|
||||
internal sealed class ScreenManagerOptions
|
||||
{
|
||||
public double X { get; set; }
|
||||
public double Y { get; set; }
|
||||
public double Width { get; set; }
|
||||
public double Height { get; set; }
|
||||
public double DpiX { get; set; }
|
||||
public double DpiY { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using Daybreak.Attributes;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Sounds")]
|
||||
internal sealed class SoundOptions
|
||||
{
|
||||
[OptionName(Name = "Sounds Enabled", Description = "If enabled, the client will play sounds.")]
|
||||
public bool Enabled { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using Daybreak.Attributes;
|
||||
using Daybreak.Models;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Theme")]
|
||||
public sealed class ThemeOptions
|
||||
{
|
||||
[OptionName(Name = "System Synchronization", Description = "If true, Daybreak will match the system light/dark mode. This setting overrides the 'Dark Mode' switch")]
|
||||
public bool SystemSynchronization { get; set; } = true;
|
||||
|
||||
[OptionName(Name = "Dark Mode", Description = "If true, Daybreak will switch to dark mode")]
|
||||
public bool DarkMode { get; set; } = true;
|
||||
|
||||
[OptionName(Name = "Color Scheme", Description = "Daybreak will apply the selected color scheme")]
|
||||
public ColorScheme Theme { get; set; } = ColorScheme.Steel;
|
||||
|
||||
[OptionName(Name = "Paintify Background", Description = "If true, Daybreak will apply a shader to make the background image look like a painting")]
|
||||
public bool BackgroundPaintify { get; set; } = true;
|
||||
|
||||
[OptionName(Name = "Blur Background", Description = "If true, the background image will be blurred")]
|
||||
public bool BackgroundBlur { get; set; } = false;
|
||||
|
||||
[OptionIgnore]
|
||||
[OptionName(Name = "Wintersday Mode", Description = "If true, Daybreak will apply a Wintersday theme")]
|
||||
public bool WintersdayMode => false;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Daybreak.Attributes;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "GWToolbox")]
|
||||
internal sealed class ToolboxOptions
|
||||
{
|
||||
[JsonProperty(nameof(DllPath))]
|
||||
[OptionName(Name = "DllPath", Description = "The path to GWToolboxdll.dll")]
|
||||
[OptionSynchronizationIgnore]
|
||||
public string? DllPath { get; set; }
|
||||
|
||||
[JsonProperty(nameof(Enabled))]
|
||||
[OptionName(Name = "Enabled", Description = "If true, Daybreak will also launch GWToolboxdll when launching GuildWars")]
|
||||
public bool Enabled { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using Daybreak.Attributes;
|
||||
using Daybreak.Models.Trade;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Trade Alerts")]
|
||||
internal sealed class TradeAlertingOptions
|
||||
{
|
||||
[OptionIgnore]
|
||||
[OptionSynchronizationIgnore]
|
||||
public TimeSpan MaxLookbackPeriod { get; set; } = TimeSpan.FromDays(31);
|
||||
|
||||
[OptionIgnore]
|
||||
[OptionSynchronizationIgnore]
|
||||
public DateTime LastCheckTime { get; set; } = DateTime.MinValue;
|
||||
|
||||
[OptionIgnore]
|
||||
public List<ITradeAlert> Alerts { get; set; } = [];
|
||||
|
||||
[OptionName(Name = "Quote Alerts Interval", Description = "The amount of seconds in between checking for alerts based on trade quotes")]
|
||||
[OptionRange<double>(MinValue = 30d, MaxValue = 1440d)]
|
||||
public double QuoteAlertsInterval { get; set; } = 30;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Daybreak.Attributes;
|
||||
using System;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Trader Quotes")]
|
||||
[OptionsSynchronizationIgnore]
|
||||
internal sealed class TraderQuotesOptions
|
||||
{
|
||||
[OptionIgnore]
|
||||
public string HttpsUri { get; set; } = "https://kamadan.gwtoolbox.com/";
|
||||
|
||||
[OptionIgnore]
|
||||
public DateTime LastCheckTime { get; set;} = DateTime.MinValue;
|
||||
|
||||
[OptionName(Name = "Cache Update Interval", Description = "The amount of minutes in between cache updates")]
|
||||
[OptionRange<double>(MinValue = 30d, MaxValue = 1440d)]
|
||||
public double CacheUpdateInterval { get; set; } = 60;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using Daybreak.Attributes;
|
||||
using Daybreak.Models.UMod;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "uMod")]
|
||||
public sealed class UModOptions
|
||||
{
|
||||
[JsonProperty(nameof(Enabled))]
|
||||
[OptionName(Name = "Enabled", Description = "If true, Daybreak will also launch uMod when launching GuildWars")]
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
[JsonProperty(nameof(AutoEnableMods))]
|
||||
[OptionName(Name = "Auto-Enable Mods", Description = "If true, mods loaded into Daybreak will be enabled by default")]
|
||||
public bool AutoEnableMods { get; set; } = true;
|
||||
|
||||
[JsonProperty(nameof(Mods))]
|
||||
[OptionIgnore]
|
||||
[OptionSynchronizationIgnore]
|
||||
public List<UModEntry> Mods { get; set; } = [];
|
||||
}
|
||||
@@ -1,49 +1,440 @@
|
||||
using Daybreak.Services.ApplicationDetection;
|
||||
using Daybreak.Services.ApplicationLifetime;
|
||||
using Daybreak.Services.Bloogum;
|
||||
using Daybreak.Services.Configuration;
|
||||
using Daybreak.Services.ApplicationLauncher;
|
||||
using Daybreak.Services.BuildTemplates;
|
||||
using Daybreak.Services.Credentials;
|
||||
using Daybreak.Services.IconRetrieve;
|
||||
using Daybreak.Services.Logging;
|
||||
using Daybreak.Services.Mutex;
|
||||
using Daybreak.Services.Privilege;
|
||||
using Daybreak.Services.Screens;
|
||||
using Daybreak.Services.Screenshots;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Daybreak.Services.Shortcuts;
|
||||
using Daybreak.Services.Updater;
|
||||
using Daybreak.Views;
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Slim;
|
||||
using System.Extensions;
|
||||
using Daybreak.Services.Options;
|
||||
using Daybreak.Models;
|
||||
using Microsoft.CorrelationVector;
|
||||
using System.Logging;
|
||||
using Daybreak.Services.Updater.PostUpdate;
|
||||
using System.Core.Extensions;
|
||||
using Daybreak.Services.Graph;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Daybreak.Services.Navigation;
|
||||
using Daybreak.Services.Onboarding;
|
||||
using Daybreak.Services.Menu;
|
||||
using Daybreak.Services.Scanner;
|
||||
using Daybreak.Services.Experience;
|
||||
using Daybreak.Services.Metrics;
|
||||
using Daybreak.Services.Monitoring;
|
||||
using Daybreak.Services.Downloads;
|
||||
using Daybreak.Services.ExceptionHandling;
|
||||
using Daybreak.Services.Startup;
|
||||
using Daybreak.Services.Startup.Actions;
|
||||
using Daybreak.Services.GuildWars;
|
||||
using Daybreak.Configuration.Options;
|
||||
using System.Configuration;
|
||||
using Daybreak.Services.UMod;
|
||||
using Daybreak.Services.Toolbox;
|
||||
using Daybreak.Views.Onboarding.UMod;
|
||||
using Daybreak.Views.Onboarding.Toolbox;
|
||||
using Daybreak.Services.Themes;
|
||||
using Daybreak.Services.TradeChat;
|
||||
using Daybreak.Views.Trade;
|
||||
using System.Net.WebSockets;
|
||||
using Daybreak.Services.Notifications;
|
||||
using Daybreak.Services.TradeChat.Models;
|
||||
using Daybreak.Services.Charts;
|
||||
using Daybreak.Services.Images;
|
||||
using Daybreak.Services.InternetChecker;
|
||||
using System;
|
||||
using Daybreak.Services.Sounds;
|
||||
using Daybreak.Services.Notifications.Models;
|
||||
using Daybreak.Models.Notifications.Handling;
|
||||
using Daybreak.Services.TradeChat.Notifications;
|
||||
using Daybreak.Views.Copy;
|
||||
using Daybreak.Services.DSOAL;
|
||||
using Daybreak.Services.Mods;
|
||||
using Daybreak.Views.Onboarding.DSOAL;
|
||||
using Daybreak.Services.Registry;
|
||||
using Daybreak.Services.DSOAL.Actions;
|
||||
using Daybreak.Services.Events;
|
||||
using Daybreak.Controls;
|
||||
using Daybreak.Models.Plugins;
|
||||
using Daybreak.Services.Plugins;
|
||||
using Daybreak.Services.Toolbox.Utilities;
|
||||
using Daybreak.Services.Injection;
|
||||
using Daybreak.Services.ReShade;
|
||||
using Daybreak.Views.Onboarding.ReShade;
|
||||
using Daybreak.Services.LaunchConfigurations;
|
||||
using Daybreak.Services.ExecutableManagement;
|
||||
using Daybreak.Views.Launch;
|
||||
using Daybreak.Services.DirectSong;
|
||||
using Daybreak.Views.Onboarding.DirectSong;
|
||||
using Daybreak.Services.SevenZip;
|
||||
using Daybreak.Services.ReShade.Notifications;
|
||||
using Daybreak.Services.UBlockOrigin;
|
||||
using Daybreak.Services.Browser;
|
||||
using Daybreak.Services.ApplicationArguments;
|
||||
using Daybreak.Services.ApplicationArguments.ArgumentHandling;
|
||||
using Daybreak.Services.Window;
|
||||
using Daybreak.Launch;
|
||||
using Daybreak.Views.Installation;
|
||||
using Daybreak.Services.Logging.Models;
|
||||
using Daybreak.Services.Toolbox.Notifications;
|
||||
using Daybreak.Services.Guildwars;
|
||||
|
||||
namespace Daybreak.Configuration
|
||||
namespace Daybreak.Configuration;
|
||||
|
||||
public class ProjectConfiguration : PluginConfigurationBase
|
||||
{
|
||||
// TODO: Credit http://bloogum.net/guildwars/
|
||||
public static class ProjectConfiguration
|
||||
public override void RegisterResolvers(IServiceManager serviceManager)
|
||||
{
|
||||
public static void RegisterServices(IServiceProducer serviceProducer)
|
||||
{
|
||||
serviceProducer.ThrowIfNull(nameof(serviceProducer));
|
||||
serviceManager.ThrowIfNull();
|
||||
|
||||
serviceProducer.RegisterSingleton<ICredentialManager, CredentialManager>();
|
||||
serviceProducer.RegisterSingleton<ILoggingDatabase, FlatLoggingDatabase>();
|
||||
serviceProducer.RegisterSingleton<ILogger, Logger>();
|
||||
serviceProducer.RegisterSingleton<ApplicationLifetimeManager>();
|
||||
serviceProducer.RegisterSingleton<ViewManager>();
|
||||
serviceProducer.RegisterSingleton<IApplicationDetector, ApplicationDetector>();
|
||||
serviceProducer.RegisterSingleton<IScreenshotProvider, ScreenshotProvider>();
|
||||
serviceProducer.RegisterSingleton<IConfigurationManager, ConfigurationManager>();
|
||||
serviceProducer.RegisterSingleton<IBloogumClient, BloogumClient>();
|
||||
serviceProducer.RegisterSingleton<CoreWebView2Environment, CoreWebView2Environment>((sp) => TaskExtensions.RunSync(() => CoreWebView2Environment.CreateAsync(null, "BrowserData", null)));
|
||||
}
|
||||
public static void RegisterLifetimeServices(IApplicationLifetimeProducer applicationLifetimeProducer)
|
||||
{
|
||||
applicationLifetimeProducer.ThrowIfNull(nameof(applicationLifetimeProducer));
|
||||
serviceManager.RegisterOptionsManager<OptionsManager>();
|
||||
serviceManager.RegisterResolver(new LoggerResolver());
|
||||
serviceManager.RegisterResolver(new ClientWebSocketResolver());
|
||||
}
|
||||
|
||||
applicationLifetimeProducer.RegisterService<ILoggingDatabase>();
|
||||
applicationLifetimeProducer.RegisterService<IScreenshotProvider>();
|
||||
}
|
||||
public static void RegisterViews(IViewProducer viewProducer)
|
||||
{
|
||||
viewProducer.ThrowIfNull(nameof(viewProducer));
|
||||
public override void RegisterServices(IServiceCollection services)
|
||||
{
|
||||
services.ThrowIfNull();
|
||||
|
||||
viewProducer.RegisterView<StartupView>();
|
||||
viewProducer.RegisterView<SettingsView>();
|
||||
}
|
||||
this.RegisterLiteCollections(services);
|
||||
this.RegisterHttpClients(services);
|
||||
services.AddSingleton<ILogsManager, JsonLogsManager>();
|
||||
services.AddSingleton<IDebugLogsWriter, Services.Logging.DebugLogsWriter>();
|
||||
services.AddSingleton<IEventViewerLogsWriter, EventViewerLogsWriter>();
|
||||
services.AddSingleton<ILoggerFactory, LoggerFactory>(sp =>
|
||||
{
|
||||
var factory = new LoggerFactory();
|
||||
factory.AddProvider(new CVLoggerProvider(sp.GetService<ILogsWriter>()));
|
||||
return factory;
|
||||
});
|
||||
services.AddSingleton<ILogsWriter, CompositeLogsWriter>(sp => new CompositeLogsWriter(
|
||||
sp.GetService<ILogsManager>()!,
|
||||
sp.GetService<IDebugLogsWriter>()!,
|
||||
sp.GetService<IEventViewerLogsWriter>()!));
|
||||
|
||||
services.AddScoped((sp) => new ScopeMetadata(new CorrelationVector()));
|
||||
services.AddSingleton<ViewManager>();
|
||||
services.AddSingleton<ProcessorUsageMonitor>();
|
||||
services.AddSingleton<MemoryUsageMonitor>();
|
||||
services.AddSingleton<DiskUsageMonitor>();
|
||||
services.AddSingleton<IViewManager, ViewManager>(sp => sp.GetRequiredService<ViewManager>());
|
||||
services.AddSingleton<IViewProducer, ViewManager>(sp => sp.GetRequiredService<ViewManager>());
|
||||
services.AddSingleton<PostUpdateActionManager>();
|
||||
services.AddSingleton<IPostUpdateActionManager>(sp => sp.GetRequiredService<PostUpdateActionManager>());
|
||||
services.AddSingleton<IPostUpdateActionProducer>(sp => sp.GetRequiredService<PostUpdateActionManager>());
|
||||
services.AddSingleton<IPostUpdateActionProvider>(sp => sp.GetRequiredService<PostUpdateActionManager>());
|
||||
services.AddSingleton<IMenuService, MenuService>();
|
||||
services.AddSingleton<IMenuServiceInitializer, MenuService>(sp => sp.GetRequiredService<IMenuService>().Cast<MenuService>());
|
||||
services.AddSingleton<IMutexHandler, MutexHandler>();
|
||||
services.AddSingleton<IShortcutManager, ShortcutManager>();
|
||||
services.AddSingleton<IMetricsService, MetricsService>();
|
||||
services.AddSingleton<IStartupActionProducer, StartupActionManager>();
|
||||
services.AddSingleton<IOptionsProducer, OptionsManager>(sp => sp.GetRequiredService<IOptionsManager>().Cast<OptionsManager>());
|
||||
services.AddSingleton<IOptionsUpdateHook, OptionsManager>(sp => sp.GetRequiredService<IOptionsManager>().Cast<OptionsManager>());
|
||||
services.AddSingleton<IOptionsProvider, OptionsManager>(sp => sp.GetRequiredService<IOptionsManager>().Cast<OptionsManager>());
|
||||
services.AddSingleton<IThemeManager, ThemeManager>();
|
||||
services.AddSingleton<INotificationService, NotificationService>();
|
||||
services.AddSingleton<INotificationProducer, NotificationService>(sp => sp.GetRequiredService<INotificationService>().Cast<NotificationService>());
|
||||
services.AddSingleton<INotificationHandlerProducer, NotificationService>(sp => sp.GetRequiredService<INotificationService>().Cast<NotificationService>());
|
||||
services.AddSingleton<ILiveChartInitializer, LiveChartInitializer>();
|
||||
services.AddSingleton<IImageCache, ImageCache>();
|
||||
services.AddSingleton<ISoundService, SoundService>();
|
||||
services.AddSingleton<IInternetCheckingService, InternetCheckingService>();
|
||||
services.AddSingleton<IConnectivityStatus, ConnectivityStatus>();
|
||||
services.AddSingleton<INotificationStorage, NotificationStorage>();
|
||||
services.AddSingleton<ITradeAlertingService, TradeAlertingService>();
|
||||
services.AddSingleton<IModsManager, ModsManager>();
|
||||
services.AddSingleton<IGuildwarsMemoryCache, GuildwarsMemoryCache>();
|
||||
services.AddSingleton<IPluginsService, PluginsService>();
|
||||
services.AddSingleton<ISplashScreenService, SplashScreenService>();
|
||||
services.AddSingleton<IGuildWarsExecutableManager, GuildWarsExecutableManager>();
|
||||
services.AddSingleton<IMemoryScanner, MemoryScanner>();
|
||||
services.AddSingleton<IGuildwarsMemoryReader, GuildwarsMemoryReader>();
|
||||
services.AddSingleton<ISevenZipExtractor, SevenZipExtractor>();
|
||||
services.AddSingleton<IGraphClient, GraphClient>();
|
||||
services.AddSingleton<IOptionsSynchronizationService, OptionsSynchronizationService>();
|
||||
services.AddSingleton<IWindowEventsHook<MainWindow>, WindowEventsHook<MainWindow>>();
|
||||
services.AddScoped<IBrowserExtensionsManager, BrowserExtensionsManager>();
|
||||
services.AddScoped<IBrowserExtensionsProducer, BrowserExtensionsManager>(sp => sp.GetRequiredService<IBrowserExtensionsManager>().Cast<BrowserExtensionsManager>());
|
||||
services.AddScoped<ICredentialManager, CredentialManager>();
|
||||
services.AddScoped<IApplicationLauncher, ApplicationLauncher>();
|
||||
services.AddScoped<IScreenshotProvider, ScreenshotProvider>();
|
||||
services.AddScoped<IOnlinePictureClient, OnlinePictureClient>();
|
||||
services.AddScoped<IApplicationUpdater, ApplicationUpdater>();
|
||||
services.AddScoped<IBuildTemplateManager, BuildTemplateManager>();
|
||||
services.AddScoped<IIconCache, IconCache>();
|
||||
services.AddScoped<IPrivilegeManager, PrivilegeManager>();
|
||||
services.AddScoped<IScreenManager, ScreenManager>();
|
||||
services.AddScoped<IOnboardingService, OnboardingService>();
|
||||
services.AddScoped<IExperienceCalculator, ExperienceCalculator>();
|
||||
services.AddScoped<IAttributePointCalculator, AttributePointCalculator>();
|
||||
services.AddScoped<IDownloadService, DownloadService>();
|
||||
services.AddScoped<IGuildWarsInstaller, IntegratedGuildwarsInstaller>();
|
||||
services.AddScoped<IExceptionHandler, ExceptionHandler>();
|
||||
services.AddScoped<ITradeChatService<KamadanTradeChatOptions>, TradeChatService<KamadanTradeChatOptions>>();
|
||||
services.AddScoped<ITradeChatService<AscalonTradeChatOptions>, TradeChatService<AscalonTradeChatOptions>>();
|
||||
services.AddScoped<ITraderQuoteService, TraderQuoteService>();
|
||||
services.AddScoped<IPriceHistoryDatabase, PriceHistoryDatabase>();
|
||||
services.AddScoped<IPriceHistoryService, PriceHistoryService>();
|
||||
services.AddScoped<IWordHighlightingService, WordHighlightingService>();
|
||||
services.AddScoped<ITradeHistoryDatabase, TradeHistoryDatabase>();
|
||||
services.AddScoped<IGuildWarsCopyService, GuildWarsCopyService>();
|
||||
services.AddScoped<IItemHashService, ItemHashService>();
|
||||
services.AddScoped<IRegistryService, RegistryService>();
|
||||
services.AddScoped<IEventNotifierService, EventNotifierService>();
|
||||
services.AddScoped<IBackgroundProvider, BackgroundProvider>();
|
||||
services.AddScoped<IToolboxClient, ToolboxClient>();
|
||||
services.AddScoped<IProcessInjector, ProcessInjector>();
|
||||
services.AddScoped<ILaunchConfigurationService, LaunchConfigurationService>();
|
||||
services.AddScoped<IBrowserHistoryManager, BrowserHistoryManager>();
|
||||
services.AddScoped<IEventService, EventService>();
|
||||
services.AddScoped<IApplicationArgumentService, ApplicationArgumentService>();
|
||||
services.AddScoped<IArgumentHandlerProducer, IApplicationArgumentService>(sp => sp.GetRequiredService<IApplicationArgumentService>());
|
||||
}
|
||||
|
||||
public override void RegisterViews(IViewProducer viewProducer)
|
||||
{
|
||||
viewProducer.ThrowIfNull();
|
||||
|
||||
viewProducer.RegisterPermanentView<Views.FocusView>();
|
||||
viewProducer.RegisterView<LauncherView>();
|
||||
viewProducer.RegisterView<UpdateView>();
|
||||
viewProducer.RegisterView<AccountsView>();
|
||||
viewProducer.RegisterView<ExecutablesView>();
|
||||
viewProducer.RegisterView<SingleBuildTemplateView>();
|
||||
viewProducer.RegisterView<BuildsListView>();
|
||||
viewProducer.RegisterView<RequestElevationView>();
|
||||
viewProducer.RegisterView<RequestDelevationView>();
|
||||
viewProducer.RegisterView<ScreenChoiceView>();
|
||||
viewProducer.RegisterView<VersionManagementView>();
|
||||
viewProducer.RegisterView<LogsView>();
|
||||
viewProducer.RegisterView<GraphAuthorizationView>();
|
||||
viewProducer.RegisterView<BuildsSynchronizationView>();
|
||||
viewProducer.RegisterView<LauncherOnboardingView>();
|
||||
viewProducer.RegisterView<MetricsView>();
|
||||
viewProducer.RegisterView<GuildWarsDownloadView>();
|
||||
viewProducer.RegisterView<GuildWarsDownloadSelectionView>();
|
||||
viewProducer.RegisterView<UModInstallingView>();
|
||||
viewProducer.RegisterView<UModInstallationChoiceView>();
|
||||
viewProducer.RegisterView<UModOnboardingEntryView>();
|
||||
viewProducer.RegisterView<UModMainView>();
|
||||
viewProducer.RegisterView<UModBrowserView>();
|
||||
viewProducer.RegisterView<ToolboxInstallationView>();
|
||||
viewProducer.RegisterView<ToolboxInstallationChoiceView>();
|
||||
viewProducer.RegisterView<ToolboxOnboardingEntryView>();
|
||||
viewProducer.RegisterView<ToolboxSwitchView>();
|
||||
viewProducer.RegisterView<ToolboxHomepageView>();
|
||||
viewProducer.RegisterView<OptionSectionView>();
|
||||
viewProducer.RegisterView<KamadanTradeChatView>();
|
||||
viewProducer.RegisterView<AscalonTradeChatView>();
|
||||
viewProducer.RegisterView<PriceQuotesView>();
|
||||
viewProducer.RegisterView<PriceHistoryView>();
|
||||
viewProducer.RegisterView<NotificationsView>();
|
||||
viewProducer.RegisterView<TradeAlertsView>();
|
||||
viewProducer.RegisterView<TradeAlertSetupView>();
|
||||
viewProducer.RegisterView<TradeNotificationView>();
|
||||
viewProducer.RegisterView<TradeAlertsChoiceView>();
|
||||
viewProducer.RegisterView<QuoteAlertSetupView>();
|
||||
viewProducer.RegisterView<GuildwarsCopySelectionView>();
|
||||
viewProducer.RegisterView<GuildwarsCopyView>();
|
||||
viewProducer.RegisterView<DSOALInstallingView>();
|
||||
viewProducer.RegisterView<DSOALOnboardingEntryView>();
|
||||
viewProducer.RegisterView<DSOALSwitchView>();
|
||||
viewProducer.RegisterView<DSOALHomepageView>();
|
||||
viewProducer.RegisterView<DSOALBrowserView>();
|
||||
viewProducer.RegisterView<PluginsView>();
|
||||
viewProducer.RegisterView<PluginsConfirmationView>();
|
||||
viewProducer.RegisterView<ReShadeInstallingView>();
|
||||
viewProducer.RegisterView<ReShadeInstallationChoiceView>();
|
||||
viewProducer.RegisterView<ReShadeOnboardingEntryView>();
|
||||
viewProducer.RegisterView<ReShadeMainView>();
|
||||
viewProducer.RegisterView<ReShadeBrowserView>();
|
||||
viewProducer.RegisterView<ReShadeStockEffectsSelectorView>();
|
||||
viewProducer.RegisterView<ReShadeConfigView>();
|
||||
viewProducer.RegisterView<ReShadePresetView>();
|
||||
viewProducer.RegisterView<LaunchConfigurationView>();
|
||||
viewProducer.RegisterView<LaunchConfigurationsView>();
|
||||
viewProducer.RegisterView<DirectSongInstallationView>();
|
||||
viewProducer.RegisterView<DirectSongInstallationChoiceView>();
|
||||
viewProducer.RegisterView<DirectSongOnboardingEntryView>();
|
||||
viewProducer.RegisterView<DirectSongSwitchView>();
|
||||
viewProducer.RegisterView<SettingsSynchronizationView>();
|
||||
viewProducer.RegisterView<TeamBuildTemplateView>();
|
||||
viewProducer.RegisterView<EventCalendarView>();
|
||||
viewProducer.RegisterView<UpdateConfirmationView>();
|
||||
viewProducer.RegisterView<GuildWarsPartySearchView>();
|
||||
}
|
||||
|
||||
public override void RegisterStartupActions(IStartupActionProducer startupActionProducer)
|
||||
{
|
||||
startupActionProducer.ThrowIfNull();
|
||||
|
||||
startupActionProducer.RegisterAction<RenameInstallerAction>();
|
||||
startupActionProducer.RegisterAction<FixSymbolicLinkStartupAction>();
|
||||
startupActionProducer.RegisterAction<UpdateUModAction>();
|
||||
startupActionProducer.RegisterAction<CredentialsOptionsMigrator>();
|
||||
startupActionProducer.RegisterAction<BrowserHistorySizeEnforcer>();
|
||||
startupActionProducer.RegisterAction<CleanupDatabases>();
|
||||
startupActionProducer.RegisterAction<DeleteOldDatabase>();
|
||||
startupActionProducer.RegisterAction<UpdateToolboxAction>();
|
||||
}
|
||||
|
||||
public override void RegisterPostUpdateActions(IPostUpdateActionProducer postUpdateActionProducer)
|
||||
{
|
||||
postUpdateActionProducer.ThrowIfNull();
|
||||
}
|
||||
|
||||
public override void RegisterOptions(IOptionsProducer optionsProducer)
|
||||
{
|
||||
optionsProducer.ThrowIfNull();
|
||||
|
||||
optionsProducer.RegisterOptions<LauncherOptions>();
|
||||
optionsProducer.RegisterOptions<SoundOptions>();
|
||||
optionsProducer.RegisterOptions<ThemeOptions>();
|
||||
|
||||
optionsProducer.RegisterOptions<BrowserOptions>();
|
||||
optionsProducer.RegisterOptions<SynchronizationOptions>();
|
||||
optionsProducer.RegisterOptions<FocusViewOptions>();
|
||||
|
||||
optionsProducer.RegisterOptions<MemoryReaderOptions>();
|
||||
optionsProducer.RegisterOptions<ImageCacheOptions>();
|
||||
|
||||
optionsProducer.RegisterOptions<BackgroundProviderOptions>();
|
||||
|
||||
optionsProducer.RegisterOptions<ToolboxOptions>();
|
||||
optionsProducer.RegisterOptions<UModOptions>();
|
||||
optionsProducer.RegisterOptions<DSOALOptions>();
|
||||
optionsProducer.RegisterOptions<ReShadeOptions>();
|
||||
|
||||
optionsProducer.RegisterOptions<ScreenManagerOptions>();
|
||||
optionsProducer.RegisterOptions<KamadanTradeChatOptions>();
|
||||
optionsProducer.RegisterOptions<AscalonTradeChatOptions>();
|
||||
optionsProducer.RegisterOptions<PriceHistoryOptions>();
|
||||
optionsProducer.RegisterOptions<TraderQuotesOptions>();
|
||||
optionsProducer.RegisterOptions<TradeAlertingOptions>();
|
||||
optionsProducer.RegisterOptions<EventNotifierOptions>();
|
||||
optionsProducer.RegisterOptions<PluginsServiceOptions>();
|
||||
optionsProducer.RegisterOptions<GuildwarsExecutableOptions>();
|
||||
optionsProducer.RegisterOptions<CredentialManagerOptions>();
|
||||
optionsProducer.RegisterOptions<LaunchConfigurationServiceOptions>();
|
||||
optionsProducer.RegisterOptions<DirectSongOptions>();
|
||||
optionsProducer.RegisterOptions<MinimapWindowOptions>();
|
||||
}
|
||||
|
||||
public override void RegisterNotificationHandlers(INotificationHandlerProducer notificationHandlerProducer)
|
||||
{
|
||||
notificationHandlerProducer.RegisterNotificationHandler<NoActionHandler>();
|
||||
notificationHandlerProducer.RegisterNotificationHandler<MessageBoxHandler>();
|
||||
notificationHandlerProducer.RegisterNotificationHandler<TradeMessageNotificationHandler>();
|
||||
notificationHandlerProducer.RegisterNotificationHandler<FixSymbolicLinkNotificationHandler>();
|
||||
notificationHandlerProducer.RegisterNotificationHandler<UpdateNotificationHandler>();
|
||||
notificationHandlerProducer.RegisterNotificationHandler<ReShadeConfigChangedHandler>();
|
||||
notificationHandlerProducer.RegisterNotificationHandler<NavigateToCalendarViewHandler>();
|
||||
notificationHandlerProducer.RegisterNotificationHandler<GuildWarsUpdateNotificationHandler>();
|
||||
notificationHandlerProducer.RegisterNotificationHandler<GuildWarsBatchUpdateNotificationHandler>();
|
||||
notificationHandlerProducer.RegisterNotificationHandler<ToolboxUpdateHandler>();
|
||||
}
|
||||
|
||||
public override void RegisterMods(IModsManager modsManager)
|
||||
{
|
||||
modsManager.RegisterMod<IGuildWarsVersionChecker, GuildWarsVersionChecker>();
|
||||
modsManager.RegisterMod<IToolboxService, ToolboxService>();
|
||||
modsManager.RegisterMod<IReShadeService, ReShadeService>();
|
||||
modsManager.RegisterMod<IUModService, UModService>();
|
||||
modsManager.RegisterMod<IDSOALService, DSOALService>();
|
||||
modsManager.RegisterMod<IGuildwarsScreenPlacer, GuildwarsScreenPlacer>();
|
||||
modsManager.RegisterMod<IDirectSongService, DirectSongService>(singleton: true);
|
||||
}
|
||||
|
||||
public override void RegisterBrowserExtensions(IBrowserExtensionsProducer browserExtensionsProducer)
|
||||
{
|
||||
browserExtensionsProducer.ThrowIfNull();
|
||||
browserExtensionsProducer.RegisterExtension<UBlockOriginService>();
|
||||
}
|
||||
|
||||
public override void RegisterLaunchArgumentHandlers(IArgumentHandlerProducer argumentHandlerProducer)
|
||||
{
|
||||
argumentHandlerProducer.ThrowIfNull();
|
||||
argumentHandlerProducer.RegisterArgumentHandler<AutoLaunchArgumentHandler>();
|
||||
}
|
||||
|
||||
private void RegisterLiteCollections(IServiceCollection services)
|
||||
{
|
||||
this.RegisterCollection<LogDTO>(services);
|
||||
this.RegisterCollection<TraderQuoteDTO>(services);
|
||||
this.RegisterCollection<NotificationDTO>(services);
|
||||
this.RegisterCollection<TraderMessageDTO>(services);
|
||||
}
|
||||
|
||||
private IServiceCollection RegisterHttpClients(IServiceCollection services)
|
||||
{
|
||||
return services
|
||||
.ThrowIfNull()
|
||||
.RegisterHttpClient<ApplicationUpdater>()
|
||||
.WithMessageHandler(this.SetupLoggingAndMetrics<ApplicationUpdater>)
|
||||
.WithDefaultRequestHeadersSetup(this.SetupDaybreakUserAgent)
|
||||
.Build()
|
||||
.RegisterHttpClient<OnlinePictureClient>()
|
||||
.WithMessageHandler(this.SetupLoggingAndMetrics<OnlinePictureClient>)
|
||||
.WithDefaultRequestHeadersSetup(this.SetupChromeImpersonationUserAgent)
|
||||
.Build()
|
||||
.RegisterHttpClient<GraphClient>()
|
||||
.WithMessageHandler(this.SetupLoggingAndMetrics<GraphClient>)
|
||||
.WithDefaultRequestHeadersSetup(this.SetupDaybreakUserAgent)
|
||||
.Build()
|
||||
.RegisterHttpClient<DownloadService>()
|
||||
.WithMessageHandler(this.SetupLoggingAndMetrics<DownloadService>)
|
||||
.WithDefaultRequestHeadersSetup(this.SetupDaybreakUserAgent)
|
||||
.Build()
|
||||
.RegisterHttpClient<TradeChatService<KamadanTradeChatOptions>>()
|
||||
.WithMessageHandler(this.SetupLoggingAndMetrics<TradeChatService<KamadanTradeChatOptions>>)
|
||||
.WithDefaultRequestHeadersSetup(this.SetupDaybreakUserAgent)
|
||||
.Build()
|
||||
.RegisterHttpClient<TradeChatService<AscalonTradeChatOptions>>()
|
||||
.WithMessageHandler(this.SetupLoggingAndMetrics<TradeChatService<AscalonTradeChatOptions>>)
|
||||
.WithDefaultRequestHeadersSetup(this.SetupDaybreakUserAgent)
|
||||
.Build()
|
||||
.RegisterHttpClient<IconCache>()
|
||||
.WithMessageHandler(this.SetupLoggingAndMetrics<IconCache>)
|
||||
.WithDefaultRequestHeadersSetup(this.SetupDaybreakUserAgent)
|
||||
.Build()
|
||||
.RegisterHttpClient<TraderQuoteService>()
|
||||
.WithMessageHandler(this.SetupLoggingAndMetrics<TraderQuoteService>)
|
||||
.WithDefaultRequestHeadersSetup(this.SetupDaybreakUserAgent)
|
||||
.Build()
|
||||
.RegisterHttpClient<PriceHistoryService>()
|
||||
.WithMessageHandler(this.SetupLoggingAndMetrics<PriceHistoryService>)
|
||||
.WithDefaultRequestHeadersSetup(this.SetupDaybreakUserAgent)
|
||||
.Build()
|
||||
.RegisterHttpClient<InternetCheckingService>()
|
||||
.WithMessageHandler(this.SetupLoggingAndMetrics<InternetCheckingService>)
|
||||
.WithDefaultRequestHeadersSetup(this.SetupDaybreakUserAgent)
|
||||
.Build()
|
||||
.RegisterHttpClient<ChromiumBrowserWrapper>()
|
||||
.WithMessageHandler(this.SetupLoggingAndMetrics<ChromiumBrowserWrapper>)
|
||||
.WithDefaultRequestHeadersSetup(this.SetupDaybreakUserAgent)
|
||||
.Build()
|
||||
.RegisterHttpClient<ToolboxClient>()
|
||||
.WithMessageHandler(this.SetupLoggingAndMetrics<ToolboxClient>)
|
||||
.WithDefaultRequestHeadersSetup(this.SetupDaybreakUserAgent)
|
||||
.Build()
|
||||
.RegisterHttpClient<ReShadeService>()
|
||||
.WithMessageHandler(this.SetupLoggingAndMetrics<ReShadeService>)
|
||||
.WithDefaultRequestHeadersSetup(this.SetupDaybreakUserAgent)
|
||||
.Build()
|
||||
.RegisterHttpClient<UModService>()
|
||||
.WithMessageHandler(this.SetupLoggingAndMetrics<UModService>)
|
||||
.WithDefaultRequestHeadersSetup(this.SetupDaybreakUserAgent)
|
||||
.Build()
|
||||
.RegisterHttpClient<UBlockOriginService>()
|
||||
.WithMessageHandler(this.SetupLoggingAndMetrics<UBlockOriginService>)
|
||||
.WithDefaultRequestHeadersSetup(this.SetupDaybreakUserAgent)
|
||||
.Build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Daybreak.Configuration;
|
||||
|
||||
public class SecretKeys
|
||||
{
|
||||
public static readonly SecretKeys AadApplicationId = new() { Key = "AadApplicationId" };
|
||||
public static readonly SecretKeys AadTenantId = new() { Key = "AadTenantId" };
|
||||
|
||||
public string Key { get; private set; } = string.Empty;
|
||||
private SecretKeys()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Extensions;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Daybreak.Configuration;
|
||||
|
||||
public static class SecretManager
|
||||
{
|
||||
private static JObject? SecretsHolder;
|
||||
|
||||
public static string GetSecret(SecretKeys secretKey)
|
||||
{
|
||||
if (SecretsHolder is null)
|
||||
{
|
||||
LoadSecrets();
|
||||
}
|
||||
|
||||
return SecretsHolder!.Value<string>(secretKey.Key)!;
|
||||
}
|
||||
|
||||
public static T GetSecret<T>(SecretKeys secretKey)
|
||||
{
|
||||
if (SecretsHolder is null)
|
||||
{
|
||||
LoadSecrets();
|
||||
}
|
||||
|
||||
return SecretsHolder!.Value<T>(secretKey.Key)!;
|
||||
}
|
||||
|
||||
private static void LoadSecrets()
|
||||
{
|
||||
var serializedSecrets = Assembly.GetExecutingAssembly().GetManifestResourceStream("Daybreak.secrets.json")!.ReadAllBytes().GetString();
|
||||
serializedSecrets = TrimUnwantedCharacters(serializedSecrets);
|
||||
SecretsHolder = JObject.Parse(serializedSecrets);
|
||||
}
|
||||
|
||||
private static string TrimUnwantedCharacters(string s)
|
||||
{
|
||||
return new string(s.Where(c =>
|
||||
char.IsWhiteSpace(c) ||
|
||||
char.IsLetterOrDigit(c) ||
|
||||
char.IsSymbol(c) ||
|
||||
char.IsSeparator(c) ||
|
||||
char.IsPunctuation(c))
|
||||
.ToArray());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<UserControl x:Class="Daybreak.Controls.AsyncImage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
xmlns:converters="clr-namespace:Daybreak.Converters"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Loaded="AsyncImage_Loaded"
|
||||
Unloaded="AsyncImage_Unloaded"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
|
||||
<converters:BooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter" TriggerValue="True"/>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Image x:Name="Image"
|
||||
VerticalAlignment="Top"
|
||||
HorizontalAlignment="Left"
|
||||
Width="{Binding ElementName=_this, Path=ActualWidth, Mode=OneWay}"
|
||||
Height="{Binding ElementName=_this, Path=ActualWidth, Mode=OneWay}"
|
||||
Source="{Binding ElementName=_this, Path=ImageSource, Mode=OneWay}"
|
||||
Stretch="{Binding ElementName=_this, Path=Stretch, Mode=OneWay}"/>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,98 @@
|
||||
using Daybreak.Services.Images;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Core.Extensions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Daybreak.Controls;
|
||||
/// <summary>
|
||||
/// Interaction logic for AsyncImage.xaml
|
||||
/// </summary>
|
||||
public partial class AsyncImage : UserControl
|
||||
{
|
||||
private readonly IImageCache imageCache;
|
||||
|
||||
private string? imageUriCache;
|
||||
private CancellationTokenSource? cancellationTokenSource;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private bool loading;
|
||||
[GenerateDependencyProperty]
|
||||
private ImageSource imageSource = default!;
|
||||
[GenerateDependencyProperty]
|
||||
private string imageUri = string.Empty;
|
||||
[GenerateDependencyProperty]
|
||||
private Stretch stretch;
|
||||
[GenerateDependencyProperty(InitialValue = BitmapScalingMode.HighQuality)]
|
||||
private BitmapScalingMode scalingMode = BitmapScalingMode.HighQuality;
|
||||
|
||||
public AsyncImage(
|
||||
IImageCache imageCache)
|
||||
{
|
||||
this.imageCache = imageCache.ThrowIfNull();
|
||||
this.InitializeComponent();
|
||||
this.SetImageScalingMode();
|
||||
}
|
||||
|
||||
public AsyncImage()
|
||||
: this(Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IImageCache>())
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnPropertyChanged(e);
|
||||
if (e.Property == ScalingModeProperty)
|
||||
{
|
||||
this.SetImageScalingMode();
|
||||
}
|
||||
else if (e.Property == ImageSourceProperty)
|
||||
{
|
||||
this.Loading = false;
|
||||
}
|
||||
else if (e.Property == ImageUriProperty &&
|
||||
this.ImageUri != this.imageUriCache)
|
||||
{
|
||||
this.Loading = true;
|
||||
this.UpdateImage(this.ImageUri);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetImageScalingMode()
|
||||
{
|
||||
RenderOptions.SetBitmapScalingMode(this.Image, this.ScalingMode);
|
||||
}
|
||||
|
||||
private void UpdateImage(string maybeUri)
|
||||
{
|
||||
this.cancellationTokenSource?.Dispose();
|
||||
this.cancellationTokenSource = new();
|
||||
var token = this.cancellationTokenSource.Token;
|
||||
new TaskFactory().StartNew(() => this.imageCache.GetImage(maybeUri), token, TaskCreationOptions.LongRunning, TaskScheduler.Current)
|
||||
.ContinueWith(async t =>
|
||||
{
|
||||
var result = await await t;
|
||||
this.Dispatcher.Invoke(() =>
|
||||
{
|
||||
this.ImageSource = result;
|
||||
this.Loading = false;
|
||||
this.imageUriCache = maybeUri;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void AsyncImage_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void AsyncImage_Unloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.cancellationTokenSource?.Dispose();
|
||||
this.cancellationTokenSource = null;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
<UserControl x:Class="Daybreak.Controls.BackButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
<Ellipse x:Name="BackgroundEllipse" Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" Visibility="Visible" Opacity="0.1" />
|
||||
<Path Fill="{Binding Foreground, ElementName=_this, Mode=OneWay}"
|
||||
Data="m30,15a15,15 0 1 1 -15,-15a15,15 0 0 1 15,15zm-28,0a13,13 0 1 0 13,-13a13,13 0 0 0 -13,13z"></Path>
|
||||
<Path Fill="{Binding Foreground, ElementName=_this, Mode=OneWay}"
|
||||
Data="m18.87,9.41l-5.58,5.59l5.58,5.59a1,1 0 0 1 0,1.41l0,0a1,1 0 0 1 -1.41,0l-6.36,-6.36a0.91,0.91 0 0 1 0,-1.28l6.36,-6.36a1,1 0 0 1 1.41,0l0,0a1,1 0 0 1 0,1.41z"></Path>
|
||||
<Ellipse Fill="Transparent" MouseEnter="Ellipse_MouseEnter" MouseLeave="Ellipse_MouseLeave" MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"></Ellipse>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</UserControl>
|
||||
@@ -1,37 +0,0 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for BackButton.xaml
|
||||
/// </summary>
|
||||
public partial class BackButton : UserControl
|
||||
{
|
||||
public event EventHandler Clicked;
|
||||
|
||||
public BackButton()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void Ellipse_MouseEnter(object sender, MouseEventArgs e)
|
||||
{
|
||||
this.BackgroundEllipse.Opacity = 0.6;
|
||||
}
|
||||
|
||||
private void Ellipse_MouseLeave(object sender, MouseEventArgs e)
|
||||
{
|
||||
this.BackgroundEllipse.Opacity = 0;
|
||||
}
|
||||
|
||||
private void Ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.ChangedButton == MouseButton.Left)
|
||||
{
|
||||
Clicked?.Invoke(this, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<UserControl x:Class="Daybreak.Controls.Buttons.AddButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls.Buttons"
|
||||
xmlns:glyphs="clr-namespace:Daybreak.Controls.Glyphs"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<local:CircularButton Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
Highlight="{StaticResource MahApps.Brushes.Accent}"
|
||||
Clicked="HighlightButton_Clicked">
|
||||
<local:CircularButton.Content>
|
||||
<Viewbox>
|
||||
<glyphs:PlusGlyph Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
Height="50"
|
||||
Width="50"
|
||||
VerticalAlignment="Top"
|
||||
HorizontalAlignment="Left"
|
||||
Margin="0, 0, 14, 14"/>
|
||||
</Viewbox>
|
||||
</local:CircularButton.Content>
|
||||
</local:CircularButton>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for AddButton.xaml
|
||||
/// </summary>
|
||||
public partial class AddButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
public ICommand? Click { get; set; }
|
||||
|
||||
public AddButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<UserControl x:Class="Daybreak.Controls.Buttons.BackButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls.Buttons"
|
||||
xmlns:glyphs="clr-namespace:Daybreak.Controls.Glyphs"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<local:CircularButton Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
Highlight="{DynamicResource MahApps.Brushes.Accent}"
|
||||
Clicked="HighlightButton_Clicked">
|
||||
<local:CircularButton.Content>
|
||||
<Viewbox Stretch="Fill" Width="60" Height="60">
|
||||
<glyphs:ArrowGlyph />
|
||||
</Viewbox>
|
||||
</local:CircularButton.Content>
|
||||
</local:CircularButton>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for BackButton.xaml
|
||||
/// </summary>
|
||||
public partial class BackButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
public BackButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<UserControl x:Class="Daybreak.Controls.Buttons.BinButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls.Buttons"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<local:CircularButton Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
Highlight="{StaticResource MahApps.Brushes.Accent}"
|
||||
Clicked="HighlightButton_Clicked">
|
||||
<local:CircularButton.Content>
|
||||
<Viewbox Width="60" Height="60">
|
||||
<Grid Margin="10">
|
||||
<Path Data="m40,7l-2,0l0,-5l-18,0l0,5l-2,0l0,-6a1,1 0 0 1 1,-1l20,0a1,1 0 0 1 1,1l0,6z"
|
||||
Fill="{StaticResource MahApps.Brushes.ThemeForeground}" Margin="11"></Path>
|
||||
<Path Data="m58,14l-2,0l0,-3l-54,0l0,3l-2,0l0,-4a1,1 0 0 1 1,-1l56,0a1,1 0 0 1 1,1l0,4z"
|
||||
Fill="{StaticResource MahApps.Brushes.ThemeForeground}" Margin="11"></Path>
|
||||
<Path Data="m51,64l-44,0a1,1 0 0 1 -1,-1l0,-48l2,0l0,47l42,0l0,-47l2,0l0,48a1,1 0 0 1 -1,1z"
|
||||
Fill="{StaticResource MahApps.Brushes.ThemeForeground}" Margin="11"></Path>
|
||||
<Rectangle Margin="38, 32, 0, 0" Width="2" Height="32" Stroke="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left"></Rectangle>
|
||||
<Rectangle Margin="26, 35, 0, 0" Width="2" Height="32" Stroke="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left"></Rectangle>
|
||||
<Rectangle Margin="50, 35, 0, 0" Width="2" Height="32" Stroke="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left"></Rectangle>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</local:CircularButton.Content>
|
||||
</local:CircularButton>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for BinButton.xaml
|
||||
/// </summary>
|
||||
public partial class BinButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
public BinButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<UserControl x:Class="Daybreak.Controls.Buttons.BrowserButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls.Buttons"
|
||||
xmlns:controls="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<local:CircularButton Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
Highlight="{StaticResource MahApps.Brushes.Accent}"
|
||||
Clicked="HighlightButton_Clicked">
|
||||
<local:CircularButton.Content>
|
||||
<Viewbox Stretch="Fill" Width="60" Height="60">
|
||||
<Grid Width="24" Height="24"
|
||||
Margin="5">
|
||||
<Path Data="m7.724,17a15.176,15.176 0 0 0 4.276,7a15.176,15.176 0 0 0 4.276,-7l-8.552,0z"
|
||||
Fill="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"/>
|
||||
<Path Data="m7,12a17.764,17.764 0 0 0 0.271,3l9.458,0a17.764,17.764 0 0 0 0.271,-3a17.764,17.764 0 0 0 -0.271,-3l-9.458,0a17.764,17.764 0 0 0 -0.271,3z"
|
||||
Fill="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"/>
|
||||
<Path Data="m23.606,9l-4.863,0a19.608,19.608 0 0 1 0.257,3a19.608,19.608 0 0 1 -0.257,3l4.863,0a11.618,11.618 0 0 0 0,-6z"
|
||||
Fill="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"/>
|
||||
<Path Data="m22.9,7a12.025,12.025 0 0 0 -7.87,-6.6a17.922,17.922 0 0 1 3.294,6.6l4.576,0z"
|
||||
Fill="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"/>
|
||||
<Path Data="m5,12a19.608,19.608 0 0 1 0.257,-3l-4.863,0a11.618,11.618 0 0 0 0,6l4.863,0a19.608,19.608 0 0 1 -0.257,-3z"
|
||||
Fill="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"/>
|
||||
<Path Data="m1.1,17a12.025,12.025 0 0 0 7.87,6.6a17.922,17.922 0 0 1 -3.294,-6.6l-4.576,0z"
|
||||
Fill="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"/>
|
||||
<Path Data="m15.03,23.6a12.025,12.025 0 0 0 7.87,-6.6l-4.576,0a17.922,17.922 0 0 1 -3.294,6.6z"
|
||||
Fill="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"/>
|
||||
<Path Data="m16.276,7a15.176,15.176 0 0 0 -4.276,-7a15.176,15.176 0 0 0 -4.276,7l8.552,0z"
|
||||
Fill="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"/>
|
||||
<Path Data="m8.97,0.4a12.025,12.025 0 0 0 -7.87,6.6l4.576,0a17.922,17.922 0 0 1 3.294,-6.6z"
|
||||
Fill="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"/>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</local:CircularButton.Content>
|
||||
</local:CircularButton>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
/// <summary>
|
||||
/// Interaction logic for CopyButton.xaml
|
||||
/// </summary>
|
||||
public partial class BrowserButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
public BrowserButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<UserControl x:Class="Daybreak.Controls.Buttons.CancelButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls.Buttons"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<local:CircularButton Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
Highlight="{StaticResource MahApps.Brushes.Accent}"
|
||||
Clicked="HighlightButton_Clicked">
|
||||
<local:CircularButton.Content>
|
||||
<Viewbox Width="60" Height="60">
|
||||
<Grid Width="30" Height="30">
|
||||
<Line X1="7" X2="23" Y1="7" Y2="23" StrokeThickness="2" Stroke="{StaticResource MahApps.Brushes.ThemeForeground}"></Line>
|
||||
<Line X1="23" X2="7" Y1="7" Y2="23" StrokeThickness="2" Stroke="{StaticResource MahApps.Brushes.ThemeForeground}"></Line>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</local:CircularButton.Content>
|
||||
</local:CircularButton>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for BackButton.xaml
|
||||
/// </summary>
|
||||
public partial class CancelButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
public CancelButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<UserControl x:Class="Daybreak.Controls.Buttons.CircularButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls.Buttons"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"></BooleanToVisibilityConverter>
|
||||
</UserControl.Resources>
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
<Ellipse Fill="{Binding ElementName=_this, Path=Highlight, Mode=OneWay}"
|
||||
Visibility="{Binding ElementName=_this, Path=IsHighlighted, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}" Opacity="0.6" />
|
||||
<Ellipse Stroke="{DynamicResource MahApps.Brushes.ThemeForeground}" StrokeThickness="3"
|
||||
VerticalAlignment="Stretch" HorizontalAlignment="Stretch"></Ellipse>
|
||||
<ContentPresenter Content="{Binding ElementName=_this, Path=Content, Mode=OneWay}"></ContentPresenter>
|
||||
<Ellipse Fill="Transparent" MouseEnter="Ellipse_MouseEnter" MouseLeave="Ellipse_MouseLeave" MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"></Ellipse>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
/// <summary>
|
||||
/// Interaction logic for HighlightButton.xaml
|
||||
/// </summary>
|
||||
public partial class CircularButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private Brush highlight = default!;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private bool isHighlighted;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private FrameworkElement content = default!;
|
||||
|
||||
public CircularButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void Ellipse_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
|
||||
{
|
||||
this.IsHighlighted = true;
|
||||
}
|
||||
|
||||
private void Ellipse_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
|
||||
{
|
||||
this.IsHighlighted = false;
|
||||
}
|
||||
|
||||
private void Ellipse_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<UserControl x:Class="Daybreak.Controls.Buttons.CopyButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls.Buttons"
|
||||
xmlns:controls="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<local:CircularButton Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
Highlight="{StaticResource MahApps.Brushes.Accent}"
|
||||
Clicked="HighlightButton_Clicked">
|
||||
<local:CircularButton.Content>
|
||||
<Viewbox Stretch="Fill" Width="60" Height="60">
|
||||
<Grid Width="80" Height="80">
|
||||
<Path Data="m28,0l-24,0c-2.21,0 -4,1.79 -4,4l0,28l4,0l0,-28l24,0l0,-4zm6,8l-22,0c-2.21,0 -4,1.79 -4,4l0,28c0,2.21 1.79,4 4,4l22,0c2.21,0 4,-1.79 4,-4l0,-28c0,-2.21 -1.79,-4 -4,-4zm0,32l-22,0l0,-28l22,0l0,28z"
|
||||
Fill="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"/>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</local:CircularButton.Content>
|
||||
</local:CircularButton>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
/// <summary>
|
||||
/// Interaction logic for CopyButton.xaml
|
||||
/// </summary>
|
||||
public partial class CopyButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
public CopyButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<UserControl x:Class="Daybreak.Controls.Buttons.FilePickerButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls.Buttons"
|
||||
xmlns:glyphs="clr-namespace:Daybreak.Controls.Glyphs"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<local:CircularButton Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
Highlight="{StaticResource MahApps.Brushes.Accent}"
|
||||
Clicked="HighlightButton_Clicked">
|
||||
<local:CircularButton.Content>
|
||||
<Viewbox Width="60" Height="60">
|
||||
<Grid>
|
||||
<glyphs:ThreeDotsGlyph Foreground="{StaticResource MahApps.Brushes.ThemeForeground}" Padding="0.5"></glyphs:ThreeDotsGlyph>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</local:CircularButton.Content>
|
||||
</local:CircularButton>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for FilePickerGlyph.xaml
|
||||
/// </summary>
|
||||
public partial class FilePickerButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
public FilePickerButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<UserControl x:Class="Daybreak.Controls.Buttons.GWToolboxButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls.Buttons"
|
||||
xmlns:glyphs="clr-namespace:Daybreak.Controls.Glyphs"
|
||||
x:Name="_this"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<local:CircularButton Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
Highlight="{StaticResource MahApps.Brushes.Accent}"
|
||||
Clicked="HighlightButton_Clicked">
|
||||
<local:CircularButton.Content>
|
||||
<Viewbox Stretch="Fill" Width="60" Height="60">
|
||||
<glyphs:GWToolboxGlyph Foreground="{StaticResource MahApps.Brushes.ThemeForeground}" Margin="10"
|
||||
IsEnabled="{Binding ElementName=_this, Path=IsEnabled, Mode=OneWay}" />
|
||||
</Viewbox>
|
||||
</local:CircularButton.Content>
|
||||
</local:CircularButton>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
/// <summary>
|
||||
/// Interaction logic for GWToolboxButton.xaml
|
||||
/// </summary>
|
||||
public partial class GWToolboxButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
public GWToolboxButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<UserControl x:Class="Daybreak.Controls.Buttons.HelpButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls.Buttons"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<local:CircularButton Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
Highlight="{StaticResource MahApps.Brushes.Accent}"
|
||||
Clicked="HighlightButton_Clicked">
|
||||
<local:CircularButton.Content>
|
||||
<Viewbox Width="60" Height="60">
|
||||
<Grid Width="30" Height="35">
|
||||
<Path Fill="{StaticResource MahApps.Brushes.ThemeForeground}" VerticalAlignment="Center" HorizontalAlignment="Center"
|
||||
Data="m4.99353,17.899l0,-1.47c0,-1.436 0.322,-2.188 1.075,-3.229l2.404,-3.3c1.254,-1.721 1.684,-2.546 1.684,-3.766c0,-2.044 -1.434,-3.335 -3.479,-3.335c-2.008,0 -3.299,1.219 -3.729,3.407c-0.036,0.215 -0.179,0.323 -0.395,0.287l-2.259,-0.395c-0.216,-0.036 -0.323,-0.179 -0.288,-0.395c0.539,-3.443 3.014,-5.703 6.744,-5.703c3.872,0 6.49,2.546 6.49,6.097c0,1.722 -0.608,2.977 -1.828,4.663l-2.403,3.3c-0.717,0.968 -0.933,1.47 -0.933,2.689l0,1.147c0,0.215 -0.143,0.358 -0.358,0.358l-2.367,0c-0.215,0.004 -0.358,-0.14 -0.358,-0.355zm-0.179,3.444c0,-0.215 0.143,-0.358 0.359,-0.358l2.726,0c0.215,0 0.358,0.144 0.358,0.358l0,3.084c0,0.216 -0.144,0.358 -0.358,0.358l-2.726,0c-0.217,0 -0.359,-0.143 -0.359,-0.358l0,-3.084z"></Path>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</local:CircularButton.Content>
|
||||
</local:CircularButton>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for AddButton.xaml
|
||||
/// </summary>
|
||||
public partial class HelpButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
public HelpButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<UserControl x:Class="Daybreak.Controls.Buttons.HighlightButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls.Buttons"
|
||||
xmlns:converters="clr-namespace:Daybreak.Converters"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<converters:MenuButtonHighlightConverter x:Key="HighlightConverter"></converters:MenuButtonHighlightConverter>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Rectangle
|
||||
Fill="{Binding ElementName=_this, Path=HighlightColor, Mode=OneWay}"
|
||||
Opacity="{Binding ElementName=_this, Path=Highlighted, Converter={StaticResource HighlightConverter}}">
|
||||
</Rectangle>
|
||||
<TextBlock Text="{Binding ElementName=_this, Path=Title, Mode=OneWay}"
|
||||
FontSize="{Binding ElementName=_this, Path=FontSize, Mode=OneWay}"
|
||||
FontFamily="{Binding ElementName=_this, Path=FontFamily, Mode=OneWay}"
|
||||
Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
VerticalAlignment="{Binding ElementName=_this, Path=VerticalContentAlignment, Mode=OneWay}"
|
||||
HorizontalAlignment="{Binding ElementName=_this, Path=HorizontalContentAlignment, Mode=OneWay}"
|
||||
TextWrapping="{Binding ElementName=_this, Path=TextWrapping, Mode=OneWay}"
|
||||
TextAlignment="{Binding ElementName=_this, Path=TextAlignment, Mode=OneWay}"
|
||||
Padding="{Binding ElementName=_this, Path=TextPadding, Mode=OneWay}" />
|
||||
<ContentPresenter
|
||||
Content="{Binding ElementName=_this, Path=ButtonContent, Mode=OneWay}"/>
|
||||
<Rectangle Fill="Transparent"
|
||||
MouseEnter="Grid_MouseEnter"
|
||||
MouseLeave="Grid_MouseLeave"
|
||||
MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" />
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
/// <summary>
|
||||
/// Interaction logic for HighlightButton.xaml
|
||||
/// </summary>
|
||||
public partial class HighlightButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private bool highlighted;
|
||||
[GenerateDependencyProperty]
|
||||
private Brush highlightColor = default!;
|
||||
[GenerateDependencyProperty(InitialValue = "")]
|
||||
private string title = string.Empty;
|
||||
[GenerateDependencyProperty(InitialValue = HorizontalAlignment.Left)]
|
||||
private HorizontalAlignment horizontalContentAlignment = HorizontalAlignment.Left;
|
||||
[GenerateDependencyProperty(InitialValue = VerticalAlignment.Top)]
|
||||
private VerticalAlignment verticalContentAlignment = VerticalAlignment.Top;
|
||||
[GenerateDependencyProperty(InitialValue = TextAlignment.Center)]
|
||||
private TextAlignment textAlignment = TextAlignment.Center;
|
||||
[GenerateDependencyProperty(InitialValue = TextWrapping.Wrap)]
|
||||
private TextWrapping textWrapping = TextWrapping.Wrap;
|
||||
[GenerateDependencyProperty]
|
||||
private Thickness textPadding = new Thickness(0);
|
||||
[GenerateDependencyProperty]
|
||||
private UIElement buttonContent = default!;
|
||||
|
||||
public HighlightButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void Grid_MouseEnter(object sender, MouseEventArgs e)
|
||||
{
|
||||
this.Highlighted = true;
|
||||
}
|
||||
|
||||
private void Grid_MouseLeave(object sender, MouseEventArgs e)
|
||||
{
|
||||
this.Highlighted = false;
|
||||
}
|
||||
|
||||
private void Rectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<UserControl x:Class="Daybreak.Controls.Buttons.HomeButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls.Buttons"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<local:CircularButton Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
Highlight="{DynamicResource MahApps.Brushes.Accent}"
|
||||
Clicked="HighlightButton_Clicked">
|
||||
<local:CircularButton.Content>
|
||||
<Viewbox Stretch="Fill">
|
||||
<Grid>
|
||||
<Path Data="m42,45.384l-14,0l0,-13l-8,0l0,13l-14,0l0,-21c0,-0.552 0.447,-1 1,-1s1,0.448 1,1l0,19l10,0l0,-13l12,0l0,13l10,0l0,-18c0,-0.552 0.447,-1 1,-1s1,0.448 1,1l0,20z"
|
||||
Fill="{DynamicResource MahApps.Brushes.ThemeForeground}"></Path>
|
||||
<Path Data="m47,24.384c-0.249,0 -0.497,-0.092 -0.691,-0.277l-22.309,-21.339l-22.309,21.339c-0.399,0.381 -1.032,0.368 -1.414,-0.031c-0.382,-0.399 -0.367,-1.032 0.031,-1.414l23.692,-22.662l23.691,22.661c0.398,0.382 0.413,1.015 0.031,1.414c-0.196,0.205 -0.458,0.309 -0.722,0.309z"
|
||||
Fill="{DynamicResource MahApps.Brushes.ThemeForeground}"></Path>
|
||||
<Path Data="m39,12.384c-0.553,0 -1,-0.448 -1,-1l0,-6l-6,0c-0.553,0 -1,-0.448 -1,-1s0.447,-1 1,-1l8,0l0,8c0,0.552 -0.447,1 -1,1z"
|
||||
Fill="{DynamicResource MahApps.Brushes.ThemeForeground}"></Path>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</local:CircularButton.Content>
|
||||
</local:CircularButton>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for HomeButton.xaml
|
||||
/// </summary>
|
||||
public partial class HomeButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
public HomeButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user