Compare commits
803 Commits
f0ced544a0
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d15c56a7b3 | ||
|
|
4e20111331 | ||
|
|
039059b4ac | ||
|
|
afbfdd8ccc | ||
|
|
57a0e89156 | ||
|
|
20505f7545 | ||
|
|
01ee72c700 | ||
|
|
b48d03ab70 | ||
|
|
c462001ff0 | ||
|
|
3d235a621a | ||
|
|
0a9174c486 | ||
|
|
f317ed9ef0 | ||
|
|
1149814f64 | ||
|
|
86f3b4c247 | ||
|
|
90686388c6 | ||
|
|
7edb9d79e5 | ||
|
|
d9a46dcb34 | ||
|
|
c4977ec826 | ||
|
|
b2e5d3d950 | ||
|
|
504f527a3f | ||
|
|
76da586b8e | ||
|
|
a3e2aaece8 | ||
|
|
691e840c7f | ||
|
|
d50f78d91d | ||
|
|
0119048c82 | ||
|
|
7ad83f4299 | ||
|
|
2515354386 | ||
|
|
db485b7acf | ||
|
|
fcb7e4e705 | ||
|
|
4bcf9041af | ||
|
|
89215793ab | ||
|
|
fe08433747 | ||
|
|
13aaf8c0f2 | ||
|
|
3248579529 | ||
|
|
bb719b3c75 | ||
|
|
9d0164aa0d | ||
|
|
0f8142c386 | ||
|
|
df3ce328b4 | ||
|
|
71f0e15bb7 | ||
|
|
4d478df181 | ||
|
|
6708162a62 | ||
|
|
68470bf576 | ||
|
|
bac915c328 | ||
|
|
a481a440c8 | ||
|
|
53f00db154 | ||
|
|
423fd49cdb | ||
|
|
20960e620c | ||
|
|
b8b45cd5ba | ||
|
|
e175eb1436 | ||
|
|
8e72239358 | ||
|
|
684880a32e | ||
|
|
d0f4e33fc0 | ||
|
|
846ba5b3c4 | ||
|
|
bb27660f85 | ||
|
|
98888a7920 | ||
|
|
7797d69a20 | ||
|
|
62624502e2 | ||
|
|
2f4657c0fb | ||
|
|
ad02dd006f | ||
|
|
a8a13ac25a | ||
|
|
4cacc3c7a7 | ||
|
|
2703227a17 | ||
|
|
b98835d277 | ||
|
|
f66f150bdc | ||
|
|
420af99a60 | ||
|
|
62dc104211 | ||
|
|
25d659e4e2 | ||
|
|
12d33d1c71 | ||
|
|
edb40c9785 | ||
|
|
a6a1ce7726 | ||
|
|
e6f6fc984a | ||
|
|
3f80cc40ff | ||
|
|
c77ad79f49 | ||
|
|
0505c5a2c5 | ||
|
|
55810e2e3a | ||
|
|
12985bf3fa | ||
|
|
2b6c747616 | ||
|
|
5cf6177eb0 | ||
|
|
17b9cf81fd | ||
|
|
5ebcc581f9 | ||
|
|
a3f90772a7 | ||
|
|
a7e0fe1d97 | ||
|
|
c564d6decf | ||
|
|
d481cfd95c | ||
|
|
244c95502a | ||
|
|
d4e01e5c27 | ||
|
|
136b654a0a | ||
|
|
4abdc26149 | ||
|
|
718be2fbae | ||
|
|
6b2b072ca4 | ||
|
|
d92963660f | ||
|
|
294a38cd2a | ||
|
|
ce31b41d3b | ||
|
|
84053df24e | ||
|
|
ea11383e8e | ||
|
|
af37a87fb1 | ||
|
|
5d4ac104c9 | ||
|
|
e3113f72eb | ||
|
|
bebbba5fec | ||
|
|
323541d694 | ||
|
|
95b5d8f377 | ||
|
|
56a7176c8b | ||
|
|
8de86924ad | ||
|
|
c72d8dadd7 | ||
|
|
22f48238cb | ||
|
|
96aad4cf34 | ||
|
|
7329985999 | ||
|
|
abc5f00fd8 | ||
|
|
ca740e933f | ||
|
|
eca35b7f54 | ||
|
|
679856585c | ||
|
|
4c9f86b29e | ||
|
|
5e9cb95e1b | ||
|
|
e2d93c2c8d | ||
|
|
544548756f | ||
|
|
651be060ea | ||
|
|
91d559dbb7 | ||
|
|
798d9da28b | ||
|
|
c18720fe59 | ||
|
|
eb699c7901 | ||
|
|
fdfde41441 | ||
|
|
4cde4d0a80 | ||
|
|
8c83dd9d46 | ||
|
|
a6377e3485 | ||
|
|
7790f9538b | ||
|
|
0b480a7889 | ||
|
|
9c43616791 | ||
|
|
8f0360daae | ||
|
|
aa3cd4ca77 | ||
|
|
df4be12532 | ||
|
|
ebc217fefe | ||
|
|
c0e41149f3 | ||
|
|
ad99eca27f | ||
|
|
ab8b08ca14 | ||
|
|
e064f5603b | ||
|
|
07b18485b2 | ||
|
|
77795ceaaa | ||
|
|
ee3e528522 | ||
|
|
fce403562c | ||
|
|
20a165b163 | ||
|
|
da617cf691 | ||
|
|
f806e1881e | ||
|
|
d71e1243c7 | ||
|
|
9cb30e8300 | ||
|
|
58d4203447 | ||
|
|
e1823fe9c0 | ||
|
|
c5b91414c1 | ||
|
|
61368c1109 | ||
|
|
65cc785988 | ||
|
|
9ac4d538aa | ||
|
|
a13c4ea260 | ||
|
|
833b7bcc14 | ||
|
|
13df229ae0 | ||
|
|
ebf93cfd7d | ||
|
|
04204d7f35 | ||
|
|
81f4669d71 | ||
|
|
3d89b13a96 | ||
|
|
b4cab46ba7 | ||
|
|
42bfd7e208 | ||
|
|
6dc2e48308 | ||
|
|
efbc746d7a | ||
|
|
28d67877af | ||
|
|
074e01bdb7 | ||
|
|
71e53d2ffc | ||
|
|
a07b2159ef | ||
|
|
f83946c8e4 | ||
|
|
5680918445 | ||
|
|
81c726c24b | ||
|
|
ee60a54866 | ||
|
|
2537b4f968 | ||
|
|
3135698ae0 | ||
|
|
cd3b78c1a5 | ||
|
|
961e8fa5b7 | ||
|
|
d6a2909dd7 | ||
|
|
11030a0856 | ||
|
|
e642e63f80 | ||
|
|
86a12f474a | ||
|
|
9b0131fb59 | ||
|
|
e8a6d86551 | ||
|
|
983ccf521c | ||
|
|
2192c564a6 | ||
|
|
f6b1901717 | ||
|
|
f49702a654 | ||
|
|
bc4338ea06 | ||
|
|
d53e2cc8a5 | ||
|
|
fd3eb34878 | ||
|
|
278ed5992d | ||
|
|
a21f0628b6 | ||
|
|
a37bef74bb | ||
|
|
fdb7d32ea6 | ||
|
|
10c2df8291 | ||
|
|
d08f902136 | ||
|
|
b6ea00d917 | ||
|
|
2a94db2896 | ||
|
|
55fad0a9d9 | ||
|
|
30976bc409 | ||
|
|
cad6b3227d | ||
|
|
ffa4623750 | ||
|
|
bce52d9bb2 | ||
|
|
b7c5ce0733 | ||
|
|
16924eca50 | ||
|
|
2b2e37fb43 | ||
|
|
bb97f7225a | ||
|
|
faee7bcd17 | ||
|
|
1285074266 | ||
|
|
2681ad3c6d | ||
|
|
56176c5a3f | ||
|
|
7aa7178673 | ||
|
|
a1e54edb1b | ||
|
|
111f6880b1 | ||
|
|
506377978c | ||
|
|
78538764c5 | ||
|
|
433fa18aba | ||
|
|
e2cfb2c4b8 | ||
|
|
dbbb892715 | ||
|
|
512a176284 | ||
|
|
9f77305be6 | ||
|
|
ec84780796 | ||
|
|
4342e35b22 | ||
|
|
bf1ca9f629 | ||
|
|
aabbfb2c40 | ||
|
|
585b61b268 | ||
|
|
f89c4e213a | ||
|
|
74a07fee00 | ||
|
|
60ff9401e2 | ||
|
|
38ee6d0a4e | ||
|
|
d598ff1905 | ||
|
|
73d106caeb | ||
|
|
cbccfdc11e | ||
|
|
7e54de0e98 | ||
|
|
19a89a4be3 | ||
|
|
d85a2a35ee | ||
|
|
c3e5f92378 | ||
|
|
90dd304ad6 | ||
|
|
7b19665dca | ||
|
|
f836e69d24 | ||
|
|
fbdf81746d | ||
|
|
da34e1d4b2 | ||
|
|
47807d5268 | ||
|
|
6083db9f2e | ||
|
|
c4808db972 | ||
|
|
7610d2137c | ||
|
|
4f548565ec | ||
|
|
3a361caa1c | ||
|
|
402efac897 | ||
|
|
9123bd524a | ||
|
|
bf475e3a35 | ||
|
|
022b8297b6 | ||
|
|
4063127942 | ||
|
|
8c30f0ff54 | ||
|
|
5ca2817c82 | ||
|
|
515fd8c5eb | ||
|
|
f14a7ab674 | ||
|
|
b586fcb708 | ||
|
|
ad5d089786 | ||
|
|
eba98dde1d | ||
|
|
98ab31bc78 | ||
|
|
99d011dd92 | ||
|
|
1c34a90cfd | ||
|
|
a18d6d62b5 | ||
|
|
1131540414 | ||
|
|
d3dc20a93f | ||
|
|
6897f0fadf | ||
|
|
b61a73aa09 | ||
|
|
271ecca9f6 | ||
|
|
24777018f0 | ||
|
|
5c6ba2f5da | ||
|
|
a44a35d92c | ||
|
|
336d888dbe | ||
|
|
0499b23ced | ||
|
|
4b0b4d42f1 | ||
|
|
26a4e84e1d | ||
|
|
573151fd31 | ||
|
|
abf5b42601 | ||
|
|
dfa6a58a57 | ||
|
|
4117ec0ce0 | ||
|
|
ca16b1acf2 | ||
|
|
e799cf4574 | ||
|
|
2ce1d0ac22 | ||
|
|
10191ae8d6 | ||
|
|
b5a1c334fb | ||
|
|
f5461a3c8c | ||
|
|
46d192ca47 | ||
|
|
39d401315c | ||
|
|
8a70f3ba96 | ||
|
|
0bea72b2d4 | ||
|
|
5d44e75985 | ||
|
|
ca1f045f4b | ||
|
|
96fb71bae7 | ||
|
|
c90d40ea5b | ||
|
|
ff06e3ac63 | ||
|
|
18490005ca | ||
|
|
a4f3fba744 | ||
|
|
55d323867b | ||
|
|
3a056f74dd | ||
|
|
1d625b40a5 | ||
|
|
9bf04d77d1 | ||
|
|
c865bbd819 | ||
|
|
f82f1a2437 | ||
|
|
d7f7f09d4d | ||
|
|
9370e0cb14 | ||
|
|
16c59dd5e0 | ||
|
|
fd7f2e2474 | ||
|
|
a9413ef666 | ||
|
|
3119d32e57 | ||
|
|
a545774f25 | ||
|
|
a18b3580d8 | ||
|
|
c06544d1cc | ||
|
|
562838fa15 | ||
|
|
06ca5eed97 | ||
|
|
e8faeeb008 | ||
|
|
49892f0fc6 | ||
|
|
0909d1047d | ||
|
|
9f498df87e | ||
|
|
e4450405cd | ||
|
|
962a9d0513 | ||
|
|
5ad8ef434a | ||
|
|
7ff5e9af52 | ||
|
|
34d8882b84 | ||
|
|
5934661746 | ||
|
|
6988a2c0ac | ||
|
|
233857c157 | ||
|
|
1adbbe5cfb | ||
|
|
b3191e534d | ||
|
|
676ef97d08 | ||
|
|
9630552a4e | ||
|
|
d3c8ec2ed2 | ||
|
|
a15ff1cb15 | ||
|
|
91ee7d2f83 | ||
|
|
c53bcf1555 | ||
|
|
fe7b545530 | ||
|
|
92a8c3ff62 | ||
|
|
69304dd283 | ||
|
|
5bb325f39d | ||
|
|
6ad66da836 | ||
|
|
30906e0dc3 | ||
|
|
b1db5a42e8 | ||
|
|
1243ab2557 | ||
|
|
154d6f23e9 | ||
|
|
a52fcfcf01 | ||
|
|
6ca11856c6 | ||
|
|
78424d1def | ||
|
|
31f560ed3f | ||
|
|
1dbbe7d1b3 | ||
|
|
0968aefde8 | ||
|
|
3b7591914a | ||
|
|
6f15424641 | ||
|
|
f4e588f42d | ||
|
|
b77072fb8a | ||
|
|
911a037a33 | ||
|
|
5445db0de7 | ||
|
|
345a9fe08d | ||
|
|
51d3f65b7e | ||
|
|
c33ccfcdc8 | ||
|
|
412ee708c2 | ||
|
|
fd3e7099f8 | ||
|
|
c1a3da4efb | ||
|
|
9f60ceb332 | ||
|
|
5c74c7c98c | ||
|
|
5a25229206 | ||
|
|
4b1e5a9c8a | ||
|
|
96eb83f2bd | ||
|
|
a1c1edd37a | ||
|
|
0198b23617 | ||
|
|
9653a0021b | ||
|
|
4b7ab5fb60 | ||
|
|
cd16048e0a | ||
|
|
905bafb92f | ||
|
|
d2be12cbb8 | ||
|
|
06dc61e37a | ||
|
|
4f616e7f9f | ||
|
|
72071a83bd | ||
|
|
b5df09be9b | ||
|
|
ba5563e55a | ||
|
|
8457189e4b | ||
|
|
e407696269 | ||
|
|
86450096f6 | ||
|
|
84fb486e1d | ||
|
|
f629999598 | ||
|
|
04e273afd1 | ||
|
|
4e3a981271 | ||
|
|
1975816dda | ||
|
|
ce71f6d8ea | ||
|
|
b622cdb745 | ||
|
|
34899cbc90 | ||
|
|
f78875265f | ||
|
|
ac1cf3a601 | ||
|
|
d5a45f185d | ||
|
|
65fc8fc89f | ||
|
|
a9814b24f7 | ||
|
|
c2e0ca7301 | ||
|
|
24feb70d61 | ||
|
|
8f12838223 | ||
|
|
ee21be082b | ||
|
|
02c510afe6 | ||
|
|
1dd3123b4a | ||
|
|
6c7ed9db83 | ||
|
|
93e2753f49 | ||
|
|
9e0046a3e7 | ||
|
|
5999a6d841 | ||
|
|
06892fd0ac | ||
|
|
cf097772f4 | ||
|
|
91cc35fc59 | ||
|
|
1229bccf59 | ||
|
|
f367fcfc6e | ||
|
|
e725555e2e | ||
|
|
2caa362fa2 | ||
|
|
33080460c0 | ||
|
|
d831b25400 | ||
|
|
18522ca00d | ||
|
|
925bf3cc92 | ||
|
|
c90a5e5528 | ||
|
|
1e82b0ce1b | ||
|
|
0729883a76 | ||
|
|
f73c556de9 | ||
|
|
71f439cb6b | ||
|
|
922e22f444 | ||
|
|
b9e420cd37 | ||
|
|
e0babfe380 | ||
|
|
43dc31bc3f | ||
|
|
c97c1bca8f | ||
|
|
af6e12d80a | ||
|
|
519570344c | ||
|
|
3ba34d2581 | ||
|
|
d02e4f124f | ||
|
|
383dc20172 | ||
|
|
b0d5901fe0 | ||
|
|
3aae63d25d | ||
|
|
6e36ff1a6f | ||
|
|
048ed6167f | ||
|
|
34d449143c | ||
|
|
97232720de | ||
|
|
2d3bc058a8 | ||
|
|
1a3ced9399 | ||
|
|
df22d053d9 | ||
|
|
63f1e3a17b | ||
|
|
b8730b1015 | ||
|
|
088c82337b | ||
|
|
489113f878 | ||
|
|
454a9ec795 | ||
|
|
bf0dbb34d8 | ||
|
|
f23fc4f1e1 | ||
|
|
a90ec95520 | ||
|
|
11f8df4656 | ||
|
|
cd84dc03d5 | ||
|
|
e23849bee7 | ||
|
|
87494078b7 | ||
|
|
ec64efd709 | ||
|
|
1f0d23b63b | ||
|
|
8e0c550547 | ||
|
|
e087c4fef9 | ||
|
|
09c11a298f | ||
|
|
50c5204a5b | ||
|
|
ab167fa144 | ||
|
|
78eba6b1fb | ||
|
|
ebfc2d8508 | ||
|
|
b0c8f01fde | ||
|
|
70ee17a48a | ||
|
|
4fb6ce06d3 | ||
|
|
b6eea313d7 | ||
|
|
f5e5918615 | ||
|
|
9800306cf8 | ||
|
|
e0ae5e2674 | ||
|
|
4763bd0b64 | ||
|
|
1e5dcfb836 | ||
|
|
1f4130a940 | ||
|
|
ec077e3d3c | ||
|
|
bc8dce82f8 | ||
|
|
5755f2deaa | ||
|
|
ab340f3447 | ||
|
|
282a994093 | ||
|
|
a3cb3ca70c | ||
|
|
af8f3aca64 | ||
|
|
bdce991d4d | ||
|
|
a90fe67c2c | ||
|
|
f5e767c23a | ||
|
|
bd44b66faa | ||
|
|
3c3606ade1 | ||
|
|
6b06205054 | ||
|
|
f2ec41103f | ||
|
|
10962945bd | ||
|
|
78e96d953d | ||
|
|
332946261b | ||
|
|
06e614f0c0 | ||
|
|
8f35f749cc | ||
|
|
fd7c85269d | ||
|
|
0621889a2e | ||
|
|
7641f9b953 | ||
|
|
0f65cd86b5 | ||
|
|
a0b7bb1c04 | ||
|
|
6f49ff87ac | ||
|
|
1d2c6d1563 | ||
|
|
da275061bf | ||
|
|
c351bad45a | ||
|
|
0aef039283 | ||
|
|
420591d376 | ||
|
|
37250f546e | ||
|
|
ba4e85a60b | ||
|
|
e7750c54da | ||
|
|
c317c55f88 | ||
|
|
3a129545c3 | ||
|
|
7b641379e3 | ||
|
|
c3cb072c34 | ||
|
|
4e16635203 | ||
|
|
ff0af7baa0 | ||
|
|
3d25c4ea75 | ||
|
|
0923331ba4 | ||
|
|
7fa250e28a | ||
|
|
e18bd6f51e | ||
|
|
e724fde5b7 | ||
|
|
5d642d2dcb | ||
|
|
f54a56392a | ||
|
|
a10334e891 | ||
|
|
c46a89168d | ||
|
|
8548285d23 | ||
|
|
d57aedc5d3 | ||
|
|
109a640fe2 | ||
|
|
60e9e51029 | ||
|
|
1b43697d06 | ||
|
|
4fa831d586 | ||
|
|
db6ddb4af7 | ||
|
|
627ab501c9 | ||
|
|
da9578bfca | ||
|
|
c9d7b6f557 | ||
|
|
6f7d112acd | ||
|
|
feec877cb8 | ||
|
|
7001d88c8b | ||
|
|
aa0a378fdc | ||
|
|
06819a9a6a | ||
|
|
fcf0d36902 | ||
|
|
20314e868e | ||
|
|
e442b5dca7 | ||
|
|
a9676b90f8 | ||
|
|
21d37fc708 | ||
|
|
4b1554757e | ||
|
|
9530b7b563 | ||
|
|
1e2ee0de12 | ||
|
|
7fec6ca636 | ||
|
|
5069551a39 | ||
|
|
b2b1ec7a67 | ||
|
|
03bbda0ac2 | ||
|
|
fe3ff09363 | ||
|
|
fe13adfdff | ||
|
|
b2b42d1eec | ||
|
|
28266cd985 | ||
|
|
68bc7590fa | ||
|
|
ecac6bb8fe | ||
|
|
ebd945c5a7 | ||
|
|
76c085b44f | ||
|
|
6cca75350e | ||
|
|
9525ecbb07 | ||
|
|
8963e31690 | ||
|
|
9da4f7dca1 | ||
|
|
75ee2fdbd0 | ||
|
|
c747176123 | ||
|
|
fd758da93d | ||
|
|
595f6e3a7a | ||
|
|
b1f0938b81 | ||
|
|
d5a6acc819 | ||
|
|
797bcac94d | ||
|
|
2ba32a4a7f | ||
|
|
75051322d5 | ||
|
|
084bacc20d | ||
|
|
ab5620dea8 | ||
|
|
c53f01793f | ||
|
|
3769f95f63 | ||
|
|
17803e31e1 | ||
|
|
2b13979fe7 | ||
|
|
d0f98cdb81 | ||
|
|
a7c159a4af | ||
|
|
c16574d9e2 | ||
|
|
bbd0b731a4 | ||
|
|
769b2b788a | ||
|
|
a32af9a8e4 | ||
|
|
d6568b2beb | ||
|
|
3ede2f7a66 | ||
|
|
19131a0296 | ||
|
|
4355c1898a | ||
|
|
debf95cf2d | ||
|
|
73db3771ee | ||
|
|
822ac5984b | ||
|
|
d1e150b306 | ||
|
|
f612be108e | ||
|
|
618fcad383 | ||
|
|
0278b99cb2 | ||
|
|
67574029aa | ||
|
|
b45d309bf1 | ||
|
|
60b24ad5e0 | ||
|
|
cace68b610 | ||
|
|
3c98f784db | ||
|
|
10da8eaa3b | ||
|
|
ef0d616cc8 | ||
|
|
fb72823ebc | ||
|
|
29868b01bb | ||
|
|
e31aa564fc | ||
|
|
3e1772ab27 | ||
|
|
4e71bb8bf5 | ||
|
|
061d5a20c9 | ||
|
|
10b68a6824 | ||
|
|
40b139c028 | ||
|
|
0c1b79bcc3 | ||
|
|
72c2fa158f | ||
|
|
3f1dda6f34 | ||
|
|
80bced3d97 | ||
|
|
bf9f204159 | ||
|
|
efab6cef79 | ||
|
|
8367927361 | ||
|
|
7cfebcf13d | ||
|
|
98fe68638c | ||
|
|
3a868f4500 | ||
|
|
ea8b188d96 | ||
|
|
8922545120 | ||
|
|
5d5923cf5c | ||
|
|
d9b694ee4b | ||
|
|
ee3dda9476 | ||
|
|
a6f9d94d24 | ||
|
|
25ee3cbbb6 | ||
|
|
caab99498c | ||
|
|
c1773ac9c7 | ||
|
|
5b5dba88ba | ||
|
|
dd9f2147b6 | ||
|
|
5acfc5d26a | ||
|
|
2f61c479a1 | ||
|
|
9c5857df82 | ||
|
|
c25514f1af | ||
|
|
a3585b34b6 | ||
|
|
a7f53e7b83 | ||
|
|
b92ee2c810 | ||
|
|
f2a1f240bc | ||
|
|
a4e6a35e6d | ||
|
|
14199ce871 | ||
|
|
edf94aa29b | ||
|
|
c1464c6ebc | ||
|
|
22b1825940 | ||
|
|
386cb74149 | ||
|
|
f334ad2275 | ||
|
|
0869044739 | ||
|
|
9e2ccf1a62 | ||
|
|
037487df9a | ||
|
|
6b01625f56 | ||
|
|
086ceee502 | ||
|
|
e6441c891b | ||
|
|
d956ccca36 | ||
|
|
3bfe702b52 | ||
|
|
b71d29fba5 | ||
|
|
9c8aae0470 | ||
|
|
e07e07e57b | ||
|
|
4d0cc97f96 | ||
|
|
461ffdf7aa | ||
|
|
a6ec430be2 | ||
|
|
0a3864f0a9 | ||
|
|
9473fd0b13 | ||
|
|
e2e9f20d1f | ||
|
|
9991555326 | ||
|
|
05bbc9bd26 | ||
|
|
5b73794899 | ||
|
|
fc8632118b | ||
|
|
f4d9464d14 | ||
|
|
61fff2bddb | ||
|
|
514d8a4969 | ||
|
|
fec3fb4b2d | ||
|
|
326ad4c2ca | ||
|
|
5d7a055094 | ||
|
|
67226b6d35 | ||
|
|
22a341cabc | ||
|
|
8cde93c892 | ||
|
|
f93f264f86 | ||
|
|
503ae01f11 | ||
|
|
c6bcd9a511 | ||
|
|
d1c17ce5f8 | ||
|
|
fffec1602f | ||
|
|
c7872fb4fd | ||
|
|
367201a924 | ||
|
|
e266742cec | ||
|
|
04f0b0a5a5 | ||
|
|
a3ee942ce3 | ||
|
|
0cf5e709b1 | ||
|
|
21c8a76f27 | ||
|
|
45caabffac | ||
|
|
15dc33a1df | ||
|
|
f88dc87433 | ||
|
|
4f1e1555bd | ||
|
|
c7945d6ed1 | ||
|
|
2bb329c5a0 | ||
|
|
7b055eee22 | ||
|
|
71eb2be35b | ||
|
|
6627e762a8 | ||
|
|
652e1c41af | ||
|
|
d037c6aa10 | ||
|
|
98eef50110 | ||
|
|
302317f522 | ||
|
|
12d5d2bb2a | ||
|
|
ee0d6ef960 | ||
|
|
2849319675 | ||
|
|
467f76b6b9 | ||
|
|
a54f4d7ed3 | ||
|
|
9349a59928 | ||
|
|
6b2fd7d106 | ||
|
|
c1a17a101a | ||
|
|
3802a50160 | ||
|
|
c977355ce7 | ||
|
|
0e0b2d85ad | ||
|
|
9c9b2df52b | ||
|
|
f0e928dcaa | ||
|
|
532ba39e1b | ||
|
|
cd96c49c78 | ||
|
|
c09c5c98e4 | ||
|
|
71758f8a42 | ||
|
|
c586b48d3e | ||
|
|
6b2c282826 | ||
|
|
db5a9f182f | ||
|
|
ba6b514523 | ||
|
|
f89d543fb0 | ||
|
|
beed1b4aeb | ||
|
|
3b9a1179b3 | ||
|
|
95cb14e322 | ||
|
|
720e61998b | ||
|
|
add702be80 | ||
|
|
7884b932ac | ||
|
|
3aac0476df | ||
|
|
38bbea519a | ||
|
|
3c803128a4 | ||
|
|
bc6281f3f8 | ||
|
|
46dd0ce593 | ||
|
|
40cf368620 | ||
|
|
b7da21e3ee | ||
|
|
c4199c0734 | ||
|
|
67404df751 | ||
|
|
5f6e713f73 | ||
|
|
63159969bc | ||
|
|
c374174536 | ||
|
|
5e53ffcac5 | ||
|
|
3074345d0f | ||
|
|
46589fe23f | ||
|
|
7873c58177 | ||
|
|
28ccde2f44 | ||
|
|
ff04309e64 | ||
|
|
1fe66edeaf | ||
|
|
715c24770d | ||
|
|
bd667e2fc6 | ||
|
|
e4bbd0e176 | ||
|
|
bb9ebe77ac | ||
|
|
da2f8b9cfd | ||
|
|
b3e5fd0848 | ||
|
|
d1a31b2116 | ||
|
|
25823e17cb | ||
|
|
45eff093e1 | ||
|
|
9429a47e1d | ||
|
|
16c9712ce2 | ||
|
|
521a3195c2 | ||
|
|
6a783a1693 | ||
|
|
f393e9e024 | ||
|
|
6b6109f04b | ||
|
|
b1a5e8030c | ||
|
|
0f48502f26 | ||
|
|
6fd0538e79 | ||
|
|
a6c531ffbd | ||
|
|
b05a17b4fb | ||
|
|
698160b701 | ||
|
|
bd4dc2651b | ||
|
|
02089982b9 | ||
|
|
3ad270162f | ||
|
|
2050ef8995 | ||
|
|
38981e1e24 | ||
|
|
32f7dedff3 | ||
|
|
e76992e39d | ||
|
|
f4dbc9f76b | ||
|
|
75f076ccd0 | ||
|
|
d9ea2ad901 | ||
|
|
5594cdb154 | ||
|
|
e8e8f2ae98 | ||
|
|
678d719f03 | ||
|
|
213a73e8a6 | ||
|
|
de5ac6cd9c | ||
|
|
f217a59b18 | ||
|
|
aaa76be8ab | ||
|
|
afd3113700 | ||
|
|
6fed069a10 | ||
|
|
40cb081586 | ||
|
|
cb53d5aac8 | ||
|
|
3db49fa170 | ||
|
|
a93abde259 | ||
|
|
85fd3c209b | ||
|
|
d5d413a8be | ||
|
|
d0c34d0826 | ||
|
|
e10fe83b4d | ||
|
|
ce26cf9a7d | ||
|
|
522ac3bbe0 | ||
|
|
3b64d10ced | ||
|
|
9d0a1c5694 | ||
|
|
de63b46d1c | ||
|
|
6b30a39ba1 | ||
|
|
a8b378971b | ||
|
|
fd71699fcc | ||
|
|
4ec92bd6ce | ||
|
|
c15dbdd595 | ||
|
|
6ee26f60ea | ||
|
|
05306feee5 | ||
|
|
fd871d8413 | ||
|
|
63c24f4a08 | ||
|
|
fbbf7f6e8f | ||
|
|
3709cbd776 | ||
|
|
70a638bd59 |
9
.cursor/rules/legacy-cpp-workers.mdc
Executable file
9
.cursor/rules/legacy-cpp-workers.mdc
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
description: C++-Worker unter src/ sind obsolet — nicht erweitern oder als Quelle für Spiellogik nutzen
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# Legacy C++ (`src/`)
|
||||||
|
|
||||||
|
- Verzeichnis **`src/`** (C++-Worker, WebSocket-Server): **obsolet**. Keine neuen Features, keine fachlichen Fixes dort planen oder umsetzen, sofern der Nutzer nicht ausdrücklich etwas anderes verlangt.
|
||||||
|
- Falukant-Hintergrundlogik: **Backend** (`backend/`), **externer Daemon**, **Frontend** — siehe `docs/LEGACY_CPP_WORKERS.md`.
|
||||||
148
.gitea/workflows/deploy.yml
Executable file
148
.gitea/workflows/deploy.yml
Executable file
@@ -0,0 +1,148 @@
|
|||||||
|
name: Deploy to production
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 2
|
||||||
|
|
||||||
|
- name: Detect vocab course changes
|
||||||
|
id: vocab_course_changes
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
BASE="${{ gitea.event.before }}"
|
||||||
|
HEAD="${{ gitea.sha }}"
|
||||||
|
|
||||||
|
if [ -z "$BASE" ] || [[ "$BASE" =~ ^0+$ ]] || ! git cat-file -e "$BASE^{commit}" 2>/dev/null; then
|
||||||
|
BASE="HEAD~1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
git diff --name-only "$BASE" "$HEAD" > changed-files.txt
|
||||||
|
cat changed-files.txt
|
||||||
|
COMMIT_MESSAGE="$(git log -1 --pretty=%B "$HEAD" || true)"
|
||||||
|
COURSE_SCRIPT_PATTERN='^backend/scripts/.*(bisaya|course|didactics|vocab)'
|
||||||
|
|
||||||
|
if echo "$COMMIT_MESSAGE" | grep -qi '\[force-deploy\]'; then
|
||||||
|
echo "force_deploy=true" >> "$GITHUB_OUTPUT"
|
||||||
|
else
|
||||||
|
echo "force_deploy=false" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -E '^(backend/scripts/.*(bisaya|course|didactics|vocab)|backend/sql/.*vocab|backend/(migrations-active|migrations-archive)/.*vocab|docs/.*(COURSE|VOCAB|BISAYA|GERMAN_FOR_BISAYA))' changed-files.txt; then
|
||||||
|
echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||||
|
else
|
||||||
|
echo "changed=false" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -E "$COURSE_SCRIPT_PATTERN" changed-files.txt >/dev/null; then
|
||||||
|
echo "course_scripts_changed=true" >> "$GITHUB_OUTPUT"
|
||||||
|
else
|
||||||
|
echo "course_scripts_changed=false" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -E '^frontend/' changed-files.txt >/dev/null; then
|
||||||
|
echo "frontend_changed=true" >> "$GITHUB_OUTPUT"
|
||||||
|
else
|
||||||
|
echo "frontend_changed=false" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Kurs-/Didaktik-Scripts werden vor dem Sync separat uebertragen.
|
||||||
|
# Fuer sie sind npm ci, Migrationen und ein Backend-Restart nicht noetig.
|
||||||
|
if grep -E '^backend/' changed-files.txt \
|
||||||
|
| grep -Ev "$COURSE_SCRIPT_PATTERN" >/dev/null; then
|
||||||
|
echo "backend_app_changed=true" >> "$GITHUB_OUTPUT"
|
||||||
|
else
|
||||||
|
echo "backend_app_changed=false" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# App-Code-Änderungen, die einen echten Deploy benötigen
|
||||||
|
if grep -E '^(frontend/|backend/|update(-frontend|-backend)?\.sh$|update\.sh$|deploy-yourpart-bluegreen\.sh$|falukant-models\.env$)' changed-files.txt \
|
||||||
|
| grep -Ev "$COURSE_SCRIPT_PATTERN" >/dev/null; then
|
||||||
|
echo "app_changed=true" >> "$GITHUB_OUTPUT"
|
||||||
|
else
|
||||||
|
echo "app_changed=false" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Prepare SSH
|
||||||
|
run: |
|
||||||
|
mkdir -p ~/.ssh
|
||||||
|
printf "%s" "${{ secrets.PROD_SSH_KEY }}" > ~/.ssh/id_ed25519
|
||||||
|
chmod 600 ~/.ssh/id_ed25519
|
||||||
|
ssh-keyscan -p "${{ secrets.PROD_PORT }}" "${{ secrets.PROD_HOST }}" >> ~/.ssh/known_hosts
|
||||||
|
|
||||||
|
- name: Test SSH connection
|
||||||
|
run: |
|
||||||
|
ssh -i ~/.ssh/id_ed25519 \
|
||||||
|
-o StrictHostKeyChecking=no \
|
||||||
|
-o BatchMode=yes \
|
||||||
|
-p "${{ secrets.PROD_PORT }}" \
|
||||||
|
"${{ secrets.PROD_USER }}@${{ secrets.PROD_HOST }}" \
|
||||||
|
"echo SSH OK"
|
||||||
|
|
||||||
|
- name: Deploy vocab course scripts without app rebuild
|
||||||
|
if: steps.vocab_course_changes.outputs.course_scripts_changed == 'true' && steps.vocab_course_changes.outputs.backend_app_changed != 'true' && steps.vocab_course_changes.outputs.force_deploy != 'true'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
tar -czf - backend/scripts \
|
||||||
|
| ssh -i ~/.ssh/id_ed25519 \
|
||||||
|
-p "${{ secrets.PROD_PORT }}" \
|
||||||
|
"${{ secrets.PROD_USER }}@${{ secrets.PROD_HOST }}" \
|
||||||
|
"sudo -n -u yourpart tar -xzf - -C /opt/yourpart"
|
||||||
|
|
||||||
|
- name: Run deployment script
|
||||||
|
if: steps.vocab_course_changes.outputs.app_changed == 'true' || steps.vocab_course_changes.outputs.force_deploy == 'true'
|
||||||
|
run: |
|
||||||
|
DEPLOY_FLAGS=""
|
||||||
|
if [ "${{ steps.vocab_course_changes.outputs.force_deploy }}" = "true" ]; then
|
||||||
|
DEPLOY_FLAGS=""
|
||||||
|
elif [ "${{ steps.vocab_course_changes.outputs.backend_app_changed }}" = "true" ] && [ "${{ steps.vocab_course_changes.outputs.frontend_changed }}" != "true" ]; then
|
||||||
|
DEPLOY_FLAGS="--skip-frontend"
|
||||||
|
elif [ "${{ steps.vocab_course_changes.outputs.frontend_changed }}" = "true" ] && [ "${{ steps.vocab_course_changes.outputs.backend_app_changed }}" != "true" ]; then
|
||||||
|
DEPLOY_FLAGS="--skip-backend"
|
||||||
|
fi
|
||||||
|
|
||||||
|
DEPLOY_TARGET="${{ secrets.PROD_DEPLOY_TARGET }}"
|
||||||
|
if [ -z "$DEPLOY_TARGET" ]; then
|
||||||
|
DEPLOY_TARGET="/opt/yourpart-green"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Deploy-Flags: ${DEPLOY_FLAGS:-<none>}"
|
||||||
|
echo "Deploy-Target: $DEPLOY_TARGET"
|
||||||
|
|
||||||
|
ssh -i ~/.ssh/id_ed25519 \
|
||||||
|
-p "${{ secrets.PROD_PORT }}" \
|
||||||
|
"${{ secrets.PROD_USER }}@${{ secrets.PROD_HOST }}" \
|
||||||
|
"/home/tsschulz/deploy-yourpart-bluegreen.sh ${DEPLOY_TARGET} ${DEPLOY_FLAGS}"
|
||||||
|
|
||||||
|
- name: Skip full deployment (no app changes)
|
||||||
|
if: steps.vocab_course_changes.outputs.app_changed != 'true' && steps.vocab_course_changes.outputs.force_deploy != 'true'
|
||||||
|
run: |
|
||||||
|
echo "Kein Full-Deploy: Es wurden keine Frontend/Backend-App-Dateien geändert."
|
||||||
|
|
||||||
|
- name: Sync vocab course content
|
||||||
|
if: steps.vocab_course_changes.outputs.changed == 'true' || steps.vocab_course_changes.outputs.force_deploy == 'true'
|
||||||
|
run: |
|
||||||
|
# Decide whether to actually run the phase3 update on the server.
|
||||||
|
# By default we run the deploy script in --dry-run mode. To enable the
|
||||||
|
# actual run set the secret PHASE3_UPDATE=1 in the repo settings.
|
||||||
|
RUN_FLAG="--dry-run"
|
||||||
|
if [ "${{ secrets.PHASE3_UPDATE }}" = "1" ]; then
|
||||||
|
RUN_FLAG=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
ssh -i ~/.ssh/id_ed25519 \
|
||||||
|
-p "${{ secrets.PROD_PORT }}" \
|
||||||
|
"${{ secrets.PROD_USER }}@${{ secrets.PROD_HOST }}" \
|
||||||
|
"cd /opt/yourpart && npm --prefix backend run sync:vocab-courses && if [ -x backend/scripts/deploy-phase3-update.sh ]; then bash backend/scripts/deploy-phase3-update.sh $RUN_FLAG; else echo 'deploy-phase3-update.sh not found or not executable'; fi"
|
||||||
29
.github/workflows/android-security.yml
vendored
Normal file
29
.github/workflows/android-security.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
name: Android Security
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- 'android/native/**'
|
||||||
|
- '.github/workflows/android-security.yml'
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- 'android/native/**'
|
||||||
|
- '.github/workflows/android-security.yml'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
scan:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: '17'
|
||||||
|
- name: Android lint
|
||||||
|
working-directory: android/native
|
||||||
|
run: ./gradlew :app:lintProductionRelease
|
||||||
|
- name: Scan dependencies with OSV
|
||||||
|
uses: google/osv-scanner-action/osv-scanner-action@v2.0.2
|
||||||
|
with:
|
||||||
|
scan-args: |-
|
||||||
|
--recursive android/native
|
||||||
50
.github/workflows/android-tests.yml
vendored
Normal file
50
.github/workflows/android-tests.yml
vendored
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
name: Android Tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- "android/native/**"
|
||||||
|
- ".github/workflows/android-tests.yml"
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- "android/native/**"
|
||||||
|
- ".github/workflows/android-tests.yml"
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
unit-tests:
|
||||||
|
name: JVM tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: android/native
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: "17"
|
||||||
|
- uses: gradle/actions/setup-gradle@v4
|
||||||
|
- run: ./gradlew :app:testLocalDebugUnitTest
|
||||||
|
|
||||||
|
instrumentation-tests:
|
||||||
|
name: Emulator tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: android/native
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: "17"
|
||||||
|
- uses: gradle/actions/setup-gradle@v4
|
||||||
|
- uses: reactivecircus/android-emulator-runner@v2
|
||||||
|
with:
|
||||||
|
api-level: 35
|
||||||
|
target: google_apis
|
||||||
|
arch: x86_64
|
||||||
|
script: ./gradlew :app:connectedLocalDebugAndroidTest
|
||||||
15
.gitignore
vendored
Normal file → Executable file
15
.gitignore
vendored
Normal file → Executable file
@@ -5,15 +5,30 @@
|
|||||||
.depbe.sh
|
.depbe.sh
|
||||||
node_modules
|
node_modules
|
||||||
node_modules/*
|
node_modules/*
|
||||||
|
# package-lock.json wird versioniert (npm ci im Deploy braucht konsistente Locks zu package.json)
|
||||||
backend/.env
|
backend/.env
|
||||||
|
backend/.env.local
|
||||||
backend/images
|
backend/images
|
||||||
backend/images/*
|
backend/images/*
|
||||||
backend/node_modules
|
backend/node_modules
|
||||||
backend/node_modules/*
|
backend/node_modules/*
|
||||||
frontend/.env
|
frontend/.env
|
||||||
|
frontend/.env.android
|
||||||
frontend/node_modules
|
frontend/node_modules
|
||||||
frontend/node_modules/*
|
frontend/node_modules/*
|
||||||
frontend/dist
|
frontend/dist
|
||||||
frontend/dist/*
|
frontend/dist/*
|
||||||
|
frontend/scripts/.i18n-de-fr-cache.json
|
||||||
|
frontend/scripts/.falukant-fr-smooth-cache.json
|
||||||
|
frontend/ceb-locale-audit-report.json
|
||||||
frontedtree.txt
|
frontedtree.txt
|
||||||
backend/dist/
|
backend/dist/
|
||||||
|
backend/data/model-cache
|
||||||
|
build
|
||||||
|
build/*
|
||||||
|
.vscode
|
||||||
|
.vscode/*
|
||||||
|
.clang-format
|
||||||
|
android/native/.gradle/
|
||||||
|
android/native/build/
|
||||||
|
android/native/local.properties
|
||||||
|
|||||||
0
.vscode/settings.json
vendored
Normal file → Executable file
0
.vscode/settings.json
vendored
Normal file → Executable file
156
CHURCH_MODELS.md
Executable file
156
CHURCH_MODELS.md
Executable file
@@ -0,0 +1,156 @@
|
|||||||
|
# Church Models - Übersicht für Daemon-Entwicklung
|
||||||
|
|
||||||
|
## 1. ChurchOfficeType (falukant_type.church_office_type)
|
||||||
|
|
||||||
|
**Schema:** `falukant_type`
|
||||||
|
**Tabelle:** `church_office_type`
|
||||||
|
**Zweck:** Definiert die verschiedenen Kirchenämter-Typen
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
id: INTEGER (PK, auto-increment)
|
||||||
|
name: STRING (z.B. "pope", "cardinal", "lay-preacher")
|
||||||
|
seatsPerRegion: INTEGER (Anzahl verfügbarer Plätze pro Region)
|
||||||
|
regionType: STRING (z.B. "country", "duchy", "city")
|
||||||
|
hierarchyLevel: INTEGER (0-8, höhere Zahl = höhere Position)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Beziehungen:**
|
||||||
|
- `hasMany` ChurchOffice (als `offices`)
|
||||||
|
- `hasMany` ChurchApplication (als `applications`)
|
||||||
|
- `hasMany` ChurchOfficeRequirement (als `requirements`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. ChurchOfficeRequirement (falukant_predefine.church_office_requirement)
|
||||||
|
|
||||||
|
**Schema:** `falukant_predefine`
|
||||||
|
**Tabelle:** `church_office_requirement`
|
||||||
|
**Zweck:** Definiert Voraussetzungen für Kirchenämter
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
id: INTEGER (PK, auto-increment)
|
||||||
|
officeTypeId: INTEGER (FK -> ChurchOfficeType.id)
|
||||||
|
prerequisiteOfficeTypeId: INTEGER (FK -> ChurchOfficeType.id, nullable)
|
||||||
|
minTitleLevel: INTEGER (nullable, optional)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Beziehungen:**
|
||||||
|
- `belongsTo` ChurchOfficeType (als `officeType`)
|
||||||
|
- `belongsTo` ChurchOfficeType (als `prerequisiteOfficeType`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. ChurchOffice (falukant_data.church_office)
|
||||||
|
|
||||||
|
**Schema:** `falukant_data`
|
||||||
|
**Tabelle:** `church_office`
|
||||||
|
**Zweck:** Speichert tatsächlich besetzte Kirchenämter
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
id: INTEGER (PK, auto-increment)
|
||||||
|
officeTypeId: INTEGER (FK -> ChurchOfficeType.id)
|
||||||
|
characterId: INTEGER (FK -> FalukantCharacter.id)
|
||||||
|
regionId: INTEGER (FK -> RegionData.id)
|
||||||
|
supervisorId: INTEGER (FK -> FalukantCharacter.id, nullable)
|
||||||
|
createdAt: DATE
|
||||||
|
updatedAt: DATE
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Beziehungen:**
|
||||||
|
- `belongsTo` ChurchOfficeType (als `type`)
|
||||||
|
- `belongsTo` FalukantCharacter (als `holder`)
|
||||||
|
- `belongsTo` FalukantCharacter (als `supervisor`)
|
||||||
|
- `belongsTo` RegionData (als `region`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. ChurchApplication (falukant_data.church_application)
|
||||||
|
|
||||||
|
**Schema:** `falukant_data`
|
||||||
|
**Tabelle:** `church_application`
|
||||||
|
**Zweck:** Speichert Bewerbungen für Kirchenämter
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
id: INTEGER (PK, auto-increment)
|
||||||
|
officeTypeId: INTEGER (FK -> ChurchOfficeType.id)
|
||||||
|
characterId: INTEGER (FK -> FalukantCharacter.id)
|
||||||
|
regionId: INTEGER (FK -> RegionData.id)
|
||||||
|
supervisorId: INTEGER (FK -> FalukantCharacter.id)
|
||||||
|
status: ENUM('pending', 'approved', 'rejected')
|
||||||
|
decisionDate: DATE (nullable)
|
||||||
|
createdAt: DATE
|
||||||
|
updatedAt: DATE
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Beziehungen:**
|
||||||
|
- `belongsTo` ChurchOfficeType (als `officeType`)
|
||||||
|
- `belongsTo` FalukantCharacter (als `applicant`)
|
||||||
|
- `belongsTo` FalukantCharacter (als `supervisor`)
|
||||||
|
- `belongsTo` RegionData (als `region`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Zusätzlich benötigte Models (für Daemon)
|
||||||
|
|
||||||
|
### RegionData (falukant_data.region)
|
||||||
|
- Wird für `regionId` in ChurchOffice und ChurchApplication benötigt
|
||||||
|
- Enthält `regionType` (country, duchy, markgravate, shire, county, city)
|
||||||
|
- Enthält `parentId` für Hierarchie
|
||||||
|
|
||||||
|
### FalukantCharacter (falukant_data.character)
|
||||||
|
- Wird für `characterId` (Inhaber/Bewerber) benötigt
|
||||||
|
- Wird für `supervisorId` benötigt
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Wichtige Queries für Daemon
|
||||||
|
|
||||||
|
### Verfügbare Positionen finden
|
||||||
|
```sql
|
||||||
|
SELECT cot.*, COUNT(co.id) as occupied_seats
|
||||||
|
FROM falukant_type.church_office_type cot
|
||||||
|
LEFT JOIN falukant_data.church_office co
|
||||||
|
ON cot.id = co.office_type_id
|
||||||
|
AND co.region_id = ?
|
||||||
|
WHERE cot.region_type = ?
|
||||||
|
GROUP BY cot.id
|
||||||
|
HAVING COUNT(co.id) < cot.seats_per_region
|
||||||
|
```
|
||||||
|
|
||||||
|
### Supervisor finden
|
||||||
|
```sql
|
||||||
|
SELECT co.*
|
||||||
|
FROM falukant_data.church_office co
|
||||||
|
JOIN falukant_type.church_office_type cot ON co.office_type_id = cot.id
|
||||||
|
WHERE co.region_id = ?
|
||||||
|
AND cot.hierarchy_level > (
|
||||||
|
SELECT hierarchy_level
|
||||||
|
FROM falukant_type.church_office_type
|
||||||
|
WHERE id = ?
|
||||||
|
)
|
||||||
|
ORDER BY cot.hierarchy_level ASC
|
||||||
|
LIMIT 1
|
||||||
|
```
|
||||||
|
|
||||||
|
### Voraussetzungen prüfen
|
||||||
|
```sql
|
||||||
|
SELECT cor.*
|
||||||
|
FROM falukant_predefine.church_office_requirement cor
|
||||||
|
WHERE cor.office_type_id = ?
|
||||||
|
```
|
||||||
|
|
||||||
|
### Bewerbungen für Supervisor
|
||||||
|
```sql
|
||||||
|
SELECT ca.*
|
||||||
|
FROM falukant_data.church_application ca
|
||||||
|
WHERE ca.supervisor_id = ?
|
||||||
|
AND ca.status = 'pending'
|
||||||
|
```
|
||||||
78
CHURCH_OFFICES.md
Executable file
78
CHURCH_OFFICES.md
Executable file
@@ -0,0 +1,78 @@
|
|||||||
|
# Kirchenämter - Hierarchie und Verfügbarkeit
|
||||||
|
|
||||||
|
## Regionstypen
|
||||||
|
- **country** (Land): Falukant
|
||||||
|
- **duchy** (Herzogtum): Hessen
|
||||||
|
- **markgravate** (Markgrafschaft): Groß-Benbach
|
||||||
|
- **shire** (Grafschaft): Siebenbachen
|
||||||
|
- **county** (Kreis): Bad Homburg, Maintal
|
||||||
|
- **city** (Stadt): Frankfurt, Oberursel, Offenbach, Königstein
|
||||||
|
|
||||||
|
## Kirchenämter (von höchstem zu niedrigstem Rang)
|
||||||
|
|
||||||
|
| Amt | Translation Key | Hierarchie-Level | Regionstyp | Plätze pro Region | Beschreibung |
|
||||||
|
|-----|----------------|-------------------|------------|-------------------|--------------|
|
||||||
|
| **Papst** | `pope` | 8 | country | 1 | Höchstes Amt, nur einer im ganzen Land |
|
||||||
|
| **Kardinal** | `cardinal` | 7 | country | 3 | Höchste Kardinäle, mehrere pro Land möglich |
|
||||||
|
| **Erzbischof** | `archbishop` | 6 | duchy | 1 | Pro Herzogtum ein Erzbischof |
|
||||||
|
| **Bischof** | `bishop` | 5 | markgravate | 1 | Pro Markgrafschaft ein Bischof |
|
||||||
|
| **Erzdiakon** | `archdeacon` | 4 | shire | 1 | Pro Grafschaft ein Erzdiakon |
|
||||||
|
| **Dekan** | `dean` | 3 | county | 1 | Pro Kreis ein Dekan |
|
||||||
|
| **Pfarrer** | `parish-priest` | 2 | city | 1 | Pro Stadt ein Pfarrer |
|
||||||
|
| **Dorfgeistlicher** | `village-priest` | 1 | city | 1 | Pro Stadt ein Dorfgeistlicher (Einstiegsposition) |
|
||||||
|
| **Laienprediger** | `lay-preacher` | 0 | city | 3 | Pro Stadt mehrere Laienprediger (niedrigste Position) |
|
||||||
|
|
||||||
|
## Verfügbare Positionen pro Regionstyp
|
||||||
|
|
||||||
|
### country (Land: Falukant)
|
||||||
|
- **Papst**: 1 Platz
|
||||||
|
- **Kardinal**: 3 Plätze
|
||||||
|
- **Gesamt**: 4 Plätze
|
||||||
|
|
||||||
|
### duchy (Herzogtum: Hessen)
|
||||||
|
- **Erzbischof**: 1 Platz
|
||||||
|
- **Gesamt**: 1 Platz
|
||||||
|
|
||||||
|
### markgravate (Markgrafschaft: Groß-Benbach)
|
||||||
|
- **Bischof**: 1 Platz
|
||||||
|
- **Gesamt**: 1 Platz
|
||||||
|
|
||||||
|
### shire (Grafschaft: Siebenbachen)
|
||||||
|
- **Erzdiakon**: 1 Platz
|
||||||
|
- **Gesamt**: 1 Platz
|
||||||
|
|
||||||
|
### county (Kreis: Bad Homburg, Maintal)
|
||||||
|
- **Dekan**: 1 Platz pro Kreis
|
||||||
|
- **Gesamt**: 1 Platz pro Kreis
|
||||||
|
|
||||||
|
### city (Stadt: Frankfurt, Oberursel, Offenbach, Königstein)
|
||||||
|
- **Pfarrer**: 1 Platz pro Stadt
|
||||||
|
- **Dorfgeistlicher**: 1 Platz pro Stadt
|
||||||
|
- **Laienprediger**: 3 Plätze pro Stadt
|
||||||
|
- **Gesamt**: 5 Plätze pro Stadt
|
||||||
|
|
||||||
|
## Hierarchie und Beförderungsweg
|
||||||
|
|
||||||
|
1. **Laienprediger** (lay-preacher) - Einstiegsposition, keine Voraussetzung
|
||||||
|
2. **Dorfgeistlicher** (village-priest) - Voraussetzung: Laienprediger
|
||||||
|
3. **Pfarrer** (parish-priest) - Voraussetzung: Dorfgeistlicher
|
||||||
|
4. **Dekan** (dean) - Voraussetzung: Pfarrer
|
||||||
|
5. **Erzdiakon** (archdeacon) - Voraussetzung: Dekan
|
||||||
|
6. **Bischof** (bishop) - Voraussetzung: Erzdiakon
|
||||||
|
7. **Erzbischof** (archbishop) - Voraussetzung: Bischof
|
||||||
|
8. **Kardinal** (cardinal) - Voraussetzung: Erzbischof
|
||||||
|
9. **Papst** (pope) - Voraussetzung: Kardinal
|
||||||
|
|
||||||
|
## Gesamtübersicht verfügbarer Positionen
|
||||||
|
|
||||||
|
- **Papst**: 1 Position (Land)
|
||||||
|
- **Kardinal**: 3 Positionen (Land)
|
||||||
|
- **Erzbischof**: 1 Position (Herzogtum)
|
||||||
|
- **Bischof**: 1 Position (Markgrafschaft)
|
||||||
|
- **Erzdiakon**: 1 Position (Grafschaft)
|
||||||
|
- **Dekan**: 2 Positionen (2 Kreise)
|
||||||
|
- **Pfarrer**: 4 Positionen (4 Städte)
|
||||||
|
- **Dorfgeistlicher**: 4 Positionen (4 Städte)
|
||||||
|
- **Laienprediger**: 12 Positionen (4 Städte × 3)
|
||||||
|
|
||||||
|
**Gesamt**: 30 Positionen im System
|
||||||
119
CMakeLists.txt
Executable file
119
CMakeLists.txt
Executable file
@@ -0,0 +1,119 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.20)
|
||||||
|
project(YourPartDaemon VERSION 1.0 LANGUAGES CXX)
|
||||||
|
|
||||||
|
# C++ Standard and Compiler Settings
|
||||||
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
# Use best available GCC for C++23 support (OpenSUSE Tumbleweed)
|
||||||
|
# Try GCC 15 first (best C++23 support), then GCC 13, then system default
|
||||||
|
find_program(GCC15_CC gcc-15)
|
||||||
|
find_program(GCC15_CXX g++-15)
|
||||||
|
find_program(GCC13_CC gcc-13)
|
||||||
|
find_program(GCC13_CXX g++-13)
|
||||||
|
|
||||||
|
if(GCC15_CC AND GCC15_CXX)
|
||||||
|
set(CMAKE_C_COMPILER ${GCC15_CC})
|
||||||
|
set(CMAKE_CXX_COMPILER ${GCC15_CXX})
|
||||||
|
message(STATUS "Using GCC 15 for best C++23 support")
|
||||||
|
elseif(GCC13_CC AND GCC13_CXX)
|
||||||
|
set(CMAKE_C_COMPILER ${GCC13_CC})
|
||||||
|
set(CMAKE_CXX_COMPILER ${GCC13_CXX})
|
||||||
|
message(STATUS "Using GCC 13 for C++23 support")
|
||||||
|
else()
|
||||||
|
message(STATUS "Using system default compiler")
|
||||||
|
endif()
|
||||||
|
# Optimize for GCC 13 with C++23
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto=auto -O3 -march=native -mtune=native")
|
||||||
|
set(CMAKE_CXX_FLAGS_DEBUG "-O1 -g -DDEBUG")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -march=native -mtune=native")
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto")
|
||||||
|
set(CMAKE_BUILD_TYPE Release)
|
||||||
|
|
||||||
|
# Include /usr/local if needed
|
||||||
|
list(APPEND CMAKE_PREFIX_PATH /usr/local)
|
||||||
|
|
||||||
|
# Find libwebsockets via pkg-config
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
pkg_check_modules(LWS REQUIRED libwebsockets)
|
||||||
|
|
||||||
|
# Find other dependencies
|
||||||
|
find_package(PostgreSQL REQUIRED)
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
find_package(nlohmann_json CONFIG REQUIRED)
|
||||||
|
|
||||||
|
# PostgreSQL C++ libpqxx
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
pkg_check_modules(LIBPQXX REQUIRED libpqxx)
|
||||||
|
|
||||||
|
# Project sources and headers
|
||||||
|
set(SOURCES
|
||||||
|
src/main.cpp
|
||||||
|
src/config.cpp
|
||||||
|
src/connection_pool.cpp
|
||||||
|
src/database.cpp
|
||||||
|
src/character_creation_worker.cpp
|
||||||
|
src/produce_worker.cpp
|
||||||
|
src/message_broker.cpp
|
||||||
|
src/websocket_server.cpp
|
||||||
|
src/stockagemanager.cpp
|
||||||
|
src/director_worker.cpp
|
||||||
|
src/valuerecalculationworker.cpp
|
||||||
|
src/usercharacterworker.cpp
|
||||||
|
src/houseworker.cpp
|
||||||
|
src/politics_worker.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(HEADERS
|
||||||
|
src/config.h
|
||||||
|
src/database.h
|
||||||
|
src/connection_pool.h
|
||||||
|
src/worker.h
|
||||||
|
src/character_creation_worker.h
|
||||||
|
src/produce_worker.h
|
||||||
|
src/message_broker.h
|
||||||
|
src/websocket_server.h
|
||||||
|
src/stockagemanager.h
|
||||||
|
src/director_worker.h
|
||||||
|
src/valuerecalculationworker.h
|
||||||
|
src/usercharacterworker.h
|
||||||
|
src/houseworker.h
|
||||||
|
src/politics_worker.h
|
||||||
|
)
|
||||||
|
|
||||||
|
# Define executable target
|
||||||
|
add_executable(yourpart-daemon ${SOURCES} ${HEADERS}
|
||||||
|
src/utils.h src/utils.cpp
|
||||||
|
src/underground_worker.h src/underground_worker.cpp)
|
||||||
|
|
||||||
|
# Include directories
|
||||||
|
target_include_directories(yourpart-daemon PRIVATE
|
||||||
|
${PostgreSQL_INCLUDE_DIRS}
|
||||||
|
${LIBPQXX_INCLUDE_DIRS}
|
||||||
|
${LWS_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Find systemd
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
pkg_check_modules(SYSTEMD REQUIRED libsystemd)
|
||||||
|
|
||||||
|
# Link libraries
|
||||||
|
target_link_libraries(yourpart-daemon PRIVATE
|
||||||
|
${PostgreSQL_LIBRARIES}
|
||||||
|
Threads::Threads
|
||||||
|
z ssl crypto
|
||||||
|
${LIBPQXX_LIBRARIES}
|
||||||
|
${LWS_LIBRARIES}
|
||||||
|
nlohmann_json::nlohmann_json
|
||||||
|
${SYSTEMD_LIBRARIES}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Installation rules
|
||||||
|
install(TARGETS yourpart-daemon DESTINATION /usr/local/bin)
|
||||||
|
|
||||||
|
# Installiere Template als Referenz ZUERST (wird vom install-Skript benötigt)
|
||||||
|
install(FILES daemon.conf DESTINATION /etc/yourpart/ RENAME daemon.conf.example)
|
||||||
|
|
||||||
|
# Intelligente Konfigurationsdatei-Installation
|
||||||
|
# Verwendet ein CMake-Skript, das nur fehlende Keys hinzufügt, ohne bestehende zu überschreiben
|
||||||
|
# Das Skript liest das Template aus /etc/yourpart/daemon.conf.example oder dem Source-Verzeichnis
|
||||||
|
install(SCRIPT cmake/install-config.cmake)
|
||||||
414
CMakeLists.txt.user
Executable file
414
CMakeLists.txt.user
Executable file
@@ -0,0 +1,414 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE QtCreatorProject>
|
||||||
|
<!-- Written by QtCreator 17.0.0, 2025-08-16T22:07:06. -->
|
||||||
|
<qtcreator>
|
||||||
|
<data>
|
||||||
|
<variable>EnvironmentId</variable>
|
||||||
|
<value type="QByteArray">{551ef6b3-a39b-43e2-9ee3-ad56e19ff4f4}</value>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||||
|
<value type="qlonglong">0</value>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||||
|
<valuemap type="QVariantMap">
|
||||||
|
<value type="bool" key="EditorConfiguration.AutoDetect">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||||
|
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||||
|
<value type="QString" key="language">Cpp</value>
|
||||||
|
<valuemap type="QVariantMap" key="value">
|
||||||
|
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||||
|
</valuemap>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||||
|
<value type="QString" key="language">QmlJS</value>
|
||||||
|
<valuemap type="QVariantMap" key="value">
|
||||||
|
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||||
|
</valuemap>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||||
|
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||||
|
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||||
|
<value type="int" key="EditorConfiguration.LineEndingBehavior">0</value>
|
||||||
|
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||||
|
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||||
|
<value type="int" key="EditorConfiguration.PreferAfterWhitespaceComments">0</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||||
|
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">2</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||||
|
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||||
|
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.UseIndenter">false</value>
|
||||||
|
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||||
|
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.tintMarginArea">true</value>
|
||||||
|
</valuemap>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||||
|
<valuemap type="QVariantMap">
|
||||||
|
<valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
|
||||||
|
<value type="bool" key="AutoTest.Framework.Boost">true</value>
|
||||||
|
<value type="bool" key="AutoTest.Framework.CTest">false</value>
|
||||||
|
<value type="bool" key="AutoTest.Framework.Catch">true</value>
|
||||||
|
<value type="bool" key="AutoTest.Framework.GTest">true</value>
|
||||||
|
<value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
|
||||||
|
<value type="bool" key="AutoTest.Framework.QtTest">true</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="bool" key="AutoTest.ApplyFilter">false</value>
|
||||||
|
<valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
|
||||||
|
<valuelist type="QVariantList" key="AutoTest.PathFilters"/>
|
||||||
|
<value type="int" key="AutoTest.RunAfterBuild">0</value>
|
||||||
|
<value type="bool" key="AutoTest.UseGlobal">true</value>
|
||||||
|
<valuemap type="QVariantMap" key="ClangTools">
|
||||||
|
<value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
|
||||||
|
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
|
||||||
|
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
|
||||||
|
<value type="int" key="ClangTools.ParallelJobs">8</value>
|
||||||
|
<value type="bool" key="ClangTools.PreferConfigFile">true</value>
|
||||||
|
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
|
||||||
|
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
|
||||||
|
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
|
||||||
|
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
|
||||||
|
</valuemap>
|
||||||
|
</valuemap>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||||
|
<valuemap type="QVariantMap">
|
||||||
|
<value type="QString" key="DeviceType">Desktop</value>
|
||||||
|
<value type="bool" key="HasPerBcDcs">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Importiertes Kit</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Importiertes Kit</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{78ff90a3-f672-45c2-ad08-343b0923896f}</value>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||||
|
<value type="QString" key="CMake.Build.Type">Debug</value>
|
||||||
|
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
|
||||||
|
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
|
||||||
|
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
|
||||||
|
-DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON
|
||||||
|
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
|
||||||
|
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
|
||||||
|
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
|
||||||
|
-DCMAKE_GENERATOR:STRING=Unix Makefiles
|
||||||
|
-DCMAKE_BUILD_TYPE:STRING=Release
|
||||||
|
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/torsten/Programs/yourpart-daemon/build/</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||||
|
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||||
|
<value type="QString">all</value>
|
||||||
|
</valuelist>
|
||||||
|
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Erstellen</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Erstellen</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Erstellen</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||||
|
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||||
|
<value type="QString">clean</value>
|
||||||
|
</valuelist>
|
||||||
|
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Erstellen</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Bereinigen</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Bereinigen</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deployment</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deployment</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.1">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||||
|
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||||
|
<value type="QString"></value>
|
||||||
|
</valuelist>
|
||||||
|
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.CMakePackageStep</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||||
|
<value type="QString" key="ApplicationManagerPlugin.Deploy.InstallPackageStep.Arguments">install-package --acknowledge</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Application Manager-Paket installieren</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.InstallPackageStep</value>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedFiles"/>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedHosts"/>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedRemotePaths"/>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedSysroots"/>
|
||||||
|
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedLocalTimes"/>
|
||||||
|
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedRemoteTimes"/>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deployment</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deployment</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.Configuration</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">2</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||||
|
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||||
|
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||||
|
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||||
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||||
|
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||||
|
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">yourpart-daemon</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">yourpart-daemon</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||||
|
<value type="QString" key="RunConfiguration.WorkingDirectory.default">/home/torsten/Programs/yourpart-daemon/build</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
|
||||||
|
<value type="QString" key="CMake.Build.Type">Debug</value>
|
||||||
|
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
|
||||||
|
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
|
||||||
|
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
|
||||||
|
-DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON
|
||||||
|
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
|
||||||
|
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
|
||||||
|
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
|
||||||
|
-DCMAKE_GENERATOR:STRING=Unix Makefiles
|
||||||
|
-DCMAKE_BUILD_TYPE:STRING=Debug
|
||||||
|
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}</value>
|
||||||
|
<value type="QString" key="CMake.Source.Directory">/mnt/share/torsten/Programs/yourpart-daemon</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/torsten/Programs/yourpart-daemon/build</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||||
|
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||||
|
<value type="QString">all</value>
|
||||||
|
</valuelist>
|
||||||
|
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Erstellen</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Erstellen</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||||
|
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||||
|
<value type="QString">clean</value>
|
||||||
|
</valuelist>
|
||||||
|
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Bereinigen</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Bereinigen</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug (importiert)</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">-1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deployment</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deployment</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.1">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||||
|
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||||
|
<value type="QString">install</value>
|
||||||
|
</valuelist>
|
||||||
|
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.CMakePackageStep</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||||
|
<value type="QString" key="ApplicationManagerPlugin.Deploy.InstallPackageStep.Arguments">install-package --acknowledge</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Application Manager-Paket installieren</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.InstallPackageStep</value>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedFiles"/>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedHosts"/>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedRemotePaths"/>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedSysroots"/>
|
||||||
|
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedLocalTimes"/>
|
||||||
|
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedRemoteTimes"/>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deployment</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deployment</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.Configuration</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">2</value>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">0</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">2</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deployment</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deployment</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.1">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||||
|
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||||
|
<value type="QString"></value>
|
||||||
|
</valuelist>
|
||||||
|
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.CMakePackageStep</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||||
|
<value type="QString" key="ApplicationManagerPlugin.Deploy.InstallPackageStep.Arguments">install-package --acknowledge</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Application Manager-Paket installieren</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.InstallPackageStep</value>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedFiles"/>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedHosts"/>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedRemotePaths"/>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedSysroots"/>
|
||||||
|
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedLocalTimes"/>
|
||||||
|
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedRemoteTimes"/>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deployment</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deployment</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.Configuration</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">2</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||||
|
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||||
|
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||||
|
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||||
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||||
|
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||||
|
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">yourpart-daemon</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">yourpart-daemon</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||||
|
<value type="QString" key="RunConfiguration.WorkingDirectory.default">/home/torsten/Programs/yourpart-daemon/build</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||||
|
</valuemap>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||||
|
<value type="qlonglong">1</value>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||||
|
<value type="int">22</value>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>Version</variable>
|
||||||
|
<value type="int">22</value>
|
||||||
|
</data>
|
||||||
|
</qtcreator>
|
||||||
205
CMakeLists.txt.user.d36652f
Executable file
205
CMakeLists.txt.user.d36652f
Executable file
@@ -0,0 +1,205 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE QtCreatorProject>
|
||||||
|
<!-- Written by QtCreator 12.0.2, 2025-07-18T07:45:58. -->
|
||||||
|
<qtcreator>
|
||||||
|
<data>
|
||||||
|
<variable>EnvironmentId</variable>
|
||||||
|
<value type="QByteArray">{d36652ff-969b-426b-a63f-1edd325096c5}</value>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||||
|
<value type="qlonglong">0</value>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||||
|
<valuemap type="QVariantMap">
|
||||||
|
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||||
|
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||||
|
<value type="QString" key="language">Cpp</value>
|
||||||
|
<valuemap type="QVariantMap" key="value">
|
||||||
|
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||||
|
</valuemap>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||||
|
<value type="QString" key="language">QmlJS</value>
|
||||||
|
<valuemap type="QVariantMap" key="value">
|
||||||
|
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||||
|
</valuemap>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||||
|
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||||
|
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||||
|
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||||
|
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||||
|
<value type="int" key="EditorConfiguration.PreferAfterWhitespaceComments">0</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||||
|
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||||
|
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||||
|
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.UseIndenter">false</value>
|
||||||
|
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||||
|
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.tintMarginArea">true</value>
|
||||||
|
</valuemap>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||||
|
<valuemap type="QVariantMap">
|
||||||
|
<valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
|
||||||
|
<value type="bool" key="AutoTest.Framework.Boost">true</value>
|
||||||
|
<value type="bool" key="AutoTest.Framework.CTest">false</value>
|
||||||
|
<value type="bool" key="AutoTest.Framework.Catch">true</value>
|
||||||
|
<value type="bool" key="AutoTest.Framework.GTest">true</value>
|
||||||
|
<value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
|
||||||
|
<value type="bool" key="AutoTest.Framework.QtTest">true</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
|
||||||
|
<value type="int" key="AutoTest.RunAfterBuild">0</value>
|
||||||
|
<value type="bool" key="AutoTest.UseGlobal">true</value>
|
||||||
|
<valuemap type="QVariantMap" key="ClangTools">
|
||||||
|
<value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
|
||||||
|
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
|
||||||
|
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
|
||||||
|
<value type="int" key="ClangTools.ParallelJobs">8</value>
|
||||||
|
<value type="bool" key="ClangTools.PreferConfigFile">true</value>
|
||||||
|
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
|
||||||
|
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
|
||||||
|
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
|
||||||
|
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="CppEditor.QuickFix">
|
||||||
|
<value type="bool" key="UseGlobalSettings">true</value>
|
||||||
|
</valuemap>
|
||||||
|
</valuemap>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||||
|
<valuemap type="QVariantMap">
|
||||||
|
<value type="QString" key="DeviceType">Desktop</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Importiertes Kit</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Importiertes Kit</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{3c6cfc13-714d-4db1-bd45-b9794643cc67}</value>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||||
|
<value type="QString" key="CMake.Build.Type">Debug</value>
|
||||||
|
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
|
||||||
|
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
|
||||||
|
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_GENERATOR:STRING=Unix Makefiles
|
||||||
|
-DCMAKE_BUILD_TYPE:STRING=Build
|
||||||
|
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
|
||||||
|
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
|
||||||
|
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
|
||||||
|
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
|
||||||
|
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}</value>
|
||||||
|
<value type="QString" key="CMake.Source.Directory">/home/torsten/Programs/yourpart-daemon</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/torsten/Programs/yourpart-daemon/build</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||||
|
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||||
|
<value type="QString">all</value>
|
||||||
|
</valuelist>
|
||||||
|
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Erstellen</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Erstellen</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Erstellen</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||||
|
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||||
|
<value type="QString">clean</value>
|
||||||
|
</valuelist>
|
||||||
|
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Erstellen</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Bereinigen</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Bereinigen</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Erstellen</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deployment</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deployment</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||||
|
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">/usr/bin/valgrind</value>
|
||||||
|
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||||
|
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||||
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||||
|
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">yourpart-daemon</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.yourpart-daemon</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">yourpart-daemon</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||||
|
<value type="QString" key="RunConfiguration.WorkingDirectory.default">/home/torsten/Programs/yourpart-daemon/build</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||||
|
</valuemap>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||||
|
<value type="qlonglong">1</value>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||||
|
<value type="int">22</value>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>Version</variable>
|
||||||
|
<value type="int">22</value>
|
||||||
|
</data>
|
||||||
|
</qtcreator>
|
||||||
0
DEPLOYMENT.md
Normal file → Executable file
0
DEPLOYMENT.md
Normal file → Executable file
259
OAUTH_CREDENTIALS_SETUP.md
Executable file
259
OAUTH_CREDENTIALS_SETUP.md
Executable file
@@ -0,0 +1,259 @@
|
|||||||
|
# OAuth Credentials Setup Guide
|
||||||
|
|
||||||
|
Anleitung zum Sammeln der OAuth-Credentials für alle 5 Provider.
|
||||||
|
|
||||||
|
## Redirect URIs
|
||||||
|
Für alle Provider benötigst du folgende Redirect URIs (ersetze `www.your-part.de` mit deiner echten Domain):
|
||||||
|
|
||||||
|
```
|
||||||
|
https://www.your-part.de/auth/oauth/callback
|
||||||
|
https://www.your-part.de/auth/oauth/user/callback
|
||||||
|
```
|
||||||
|
|
||||||
|
Lokal zum Testen:
|
||||||
|
```
|
||||||
|
http://localhost:3000/auth/oauth/callback
|
||||||
|
http://localhost:3000/auth/oauth/user/callback
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Google
|
||||||
|
|
||||||
|
### Credentials besorgen:
|
||||||
|
|
||||||
|
1. Öffne [Google Cloud Console](https://console.cloud.google.com/)
|
||||||
|
2. Erstelle ein neues Projekt oder wähle ein bestehendes
|
||||||
|
3. Navigiere zu **APIs & Services** → **Credentials**
|
||||||
|
4. Klick **+ CREATE CREDENTIALS** → **OAuth 2.0 Client IDs**
|
||||||
|
5. Wähle **Web application**
|
||||||
|
6. Füge unter **Authorized redirect URIs** hinzu:
|
||||||
|
- `https://www.your-part.de/auth/oauth/callback`
|
||||||
|
- `https://www.your-part.de/auth/oauth/user/callback`
|
||||||
|
7. Speichern und die **Client ID** und **Client Secret** kopieren
|
||||||
|
|
||||||
|
### .env:
|
||||||
|
```env
|
||||||
|
OAUTH_GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
|
||||||
|
OAUTH_GOOGLE_CLIENT_SECRET=your-client-secret
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Microsoft Azure
|
||||||
|
|
||||||
|
### Credentials besorgen:
|
||||||
|
|
||||||
|
1. Öffne [Azure Portal](https://portal.azure.com/)
|
||||||
|
2. Navigiere zu **Azure Active Directory** → **App registrations** → **+ New registration**
|
||||||
|
3. Gib einen Namen ein (z.B. "YourPart OAuth")
|
||||||
|
4. Wähle **Accounts in any organizational directory (Any Azure AD directory - Multitenant)**
|
||||||
|
5. Bei **Redirect URI** wähle **Web** und füge ein:
|
||||||
|
- `https://www.your-part.de/auth/oauth/callback`
|
||||||
|
6. Klick **Register**
|
||||||
|
7. Notiere die **Application (client) ID**
|
||||||
|
8. Gehe zu **Certificates & secrets** → **+ New client secret**
|
||||||
|
9. Erstelle ein Secret und kopiere den **Value** (nicht die ID!)
|
||||||
|
10. Gehe zu **Token configuration** und stelle sicher, dass die richtigen Claims enthalten sind
|
||||||
|
|
||||||
|
### Zusätzliche URI hinzufügen:
|
||||||
|
1. Gehe zu **Authentication**
|
||||||
|
2. Unter **Redirect URIs** klick **+ Add URI**
|
||||||
|
3. Füge hinzu: `https://www.your-part.de/auth/oauth/user/callback`
|
||||||
|
|
||||||
|
### .env:
|
||||||
|
```env
|
||||||
|
OAUTH_MICROSOFT_CLIENT_ID=your-application-id
|
||||||
|
OAUTH_MICROSOFT_CLIENT_SECRET=your-client-secret-value
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Keycloak
|
||||||
|
|
||||||
|
Keycloak ist ein Open-Source OIDC Provider. Du kannst ihn selbst hosten oder eine gehostete Lösung nutzen.
|
||||||
|
|
||||||
|
### Option A: Selbst gehostet mit Docker
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d \
|
||||||
|
-p 8080:8080 \
|
||||||
|
-e KEYCLOAK_ADMIN=admin \
|
||||||
|
-e KEYCLOAK_ADMIN_PASSWORD=admin \
|
||||||
|
quay.io/keycloak/keycloak:latest \
|
||||||
|
start-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Dann:
|
||||||
|
1. Öffne http://localhost:8080
|
||||||
|
2. Login mit `admin` / `admin`
|
||||||
|
3. **Realm erstellen**: Oben links Dropdown → **Create realm**
|
||||||
|
- Name: `yourpart` (oder beliebig)
|
||||||
|
4. Im neuen Realm: **Clients** → **Create client**
|
||||||
|
- Client ID: `yourpart`
|
||||||
|
- Client Protocol: `openid-connect`
|
||||||
|
- Access Type: `confidential`
|
||||||
|
5. Im **Settings** Tab:
|
||||||
|
- Valid Redirect URIs:
|
||||||
|
```
|
||||||
|
https://www.your-part.de/auth/oauth/callback
|
||||||
|
https://www.your-part.de/auth/oauth/user/callback
|
||||||
|
```
|
||||||
|
6. Speichern
|
||||||
|
7. Gehe zu **Credentials** Tab
|
||||||
|
- **Client Secret** kopieren
|
||||||
|
|
||||||
|
### Option B: Gehosteter Service
|
||||||
|
- [Keycloak.cloud](https://www.keycloak.cloud/) oder
|
||||||
|
- [Red Hat Managed Keycloak](https://www.keycloak.org/cloud/)
|
||||||
|
|
||||||
|
### .env:
|
||||||
|
```env
|
||||||
|
OAUTH_KEYCLOAK_ISSUER=https://your-keycloak-domain/realms/yourpart
|
||||||
|
OAUTH_KEYCLOAK_CLIENT_ID=yourpart
|
||||||
|
OAUTH_KEYCLOAK_CLIENT_SECRET=your-client-secret
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. ORY Hydra / ORY Cloud
|
||||||
|
|
||||||
|
ORY ist ein moderner OIDC Provider. Am einfachsten ist ORY Cloud.
|
||||||
|
|
||||||
|
### Option A: ORY Cloud (empfohlen)
|
||||||
|
|
||||||
|
1. Öffne [ORY Cloud Console](https://console.ory.sh/)
|
||||||
|
2. Registriere dich oder logge dich ein
|
||||||
|
3. Erstelle ein neues **Project**
|
||||||
|
4. Gehe zu **Applications**
|
||||||
|
5. Klick **Create New Application**
|
||||||
|
6. Gib einen Namen ein (z.B. "YourPart")
|
||||||
|
7. Unter **Redirect URLs** füge ein:
|
||||||
|
```
|
||||||
|
https://www.your-part.de/auth/oauth/callback
|
||||||
|
https://www.your-part.de/auth/oauth/user/callback
|
||||||
|
```
|
||||||
|
8. Speichern
|
||||||
|
9. Die **Client ID** und **Client Secret** werden angezeigt
|
||||||
|
10. Finde deine **Issuer URL** in den Project Settings (meist `https://your-project-slug.eu.hydra.cloud`)
|
||||||
|
|
||||||
|
### Option B: Selbst gehostet (komplex)
|
||||||
|
|
||||||
|
Siehe [ORY Hydra Dokumentation](https://www.ory.sh/hydra/docs/)
|
||||||
|
|
||||||
|
### .env:
|
||||||
|
```env
|
||||||
|
OAUTH_ORY_ISSUER=https://your-project-slug.eu.hydra.cloud
|
||||||
|
OAUTH_ORY_CLIENT_ID=your-client-id
|
||||||
|
OAUTH_ORY_CLIENT_SECRET=your-client-secret
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. ZITADEL
|
||||||
|
|
||||||
|
ZITADEL ist ein Zero-Trust Identity Platform als SaaS.
|
||||||
|
|
||||||
|
### Credentials besorgen:
|
||||||
|
|
||||||
|
1. Öffne [ZITADEL Console](https://zitadel.cloud/)
|
||||||
|
2. Registriere dich oder logge dich ein
|
||||||
|
3. Erstelle eine neue **Organization** (oder verwende die existierende)
|
||||||
|
4. Gehe zu **Projects** → **+ New Project**
|
||||||
|
5. Gib einen Namen ein (z.B. "YourPart")
|
||||||
|
6. Gehe zum Projekt → **Applications** → **+ New Application**
|
||||||
|
7. Wähle **Type: Web**
|
||||||
|
8. Gib einen Namen ein
|
||||||
|
9. Bei **Redirect URIs** füge ein:
|
||||||
|
```
|
||||||
|
https://www.your-part.de/auth/oauth/callback
|
||||||
|
https://www.your-part.de/auth/oauth/user/callback
|
||||||
|
```
|
||||||
|
10. Speichern
|
||||||
|
11. Unter **Client Information** kopiere:
|
||||||
|
- **Client ID**
|
||||||
|
- **Client Secret** (falls sichtbar, sonst im "CREDENTIALS" Tab generieren)
|
||||||
|
12. Finde deine **Issuer URL** in den Organization Settings (meist `https://your-instance.zitadel.cloud`)
|
||||||
|
|
||||||
|
### .env:
|
||||||
|
```env
|
||||||
|
OAUTH_ZITADEL_ISSUER=https://your-instance.zitadel.cloud
|
||||||
|
OAUTH_ZITADEL_CLIENT_ID=your-client-id
|
||||||
|
OAUTH_ZITADEL_CLIENT_SECRET=your-client-secret
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Komplette .env für alle 5 Provider
|
||||||
|
|
||||||
|
```env
|
||||||
|
# Google
|
||||||
|
OAUTH_GOOGLE_CLIENT_ID=...
|
||||||
|
OAUTH_GOOGLE_CLIENT_SECRET=...
|
||||||
|
|
||||||
|
# Microsoft
|
||||||
|
OAUTH_MICROSOFT_CLIENT_ID=...
|
||||||
|
OAUTH_MICROSOFT_CLIENT_SECRET=...
|
||||||
|
|
||||||
|
# Keycloak
|
||||||
|
OAUTH_KEYCLOAK_ISSUER=...
|
||||||
|
OAUTH_KEYCLOAK_CLIENT_ID=...
|
||||||
|
OAUTH_KEYCLOAK_CLIENT_SECRET=...
|
||||||
|
|
||||||
|
# ORY
|
||||||
|
OAUTH_ORY_ISSUER=...
|
||||||
|
OAUTH_ORY_CLIENT_ID=...
|
||||||
|
OAUTH_ORY_CLIENT_SECRET=...
|
||||||
|
|
||||||
|
# ZITADEL
|
||||||
|
OAUTH_ZITADEL_ISSUER=...
|
||||||
|
OAUTH_ZITADEL_CLIENT_ID=...
|
||||||
|
OAUTH_ZITADEL_CLIENT_SECRET=...
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Schnell-Checkliste
|
||||||
|
|
||||||
|
- [ ] Google: Client ID & Secret
|
||||||
|
- [ ] Microsoft: Application ID & Client Secret
|
||||||
|
- [ ] Keycloak: Issuer, Client ID, Secret
|
||||||
|
- [ ] ORY: Issuer, Client ID, Secret
|
||||||
|
- [ ] ZITADEL: Issuer, Client ID, Secret
|
||||||
|
- [ ] Alle Redirect URIs in den Providern konfiguriert
|
||||||
|
- [ ] .env datei aktualisiert
|
||||||
|
- [ ] Server neu gestartet (`npm restart`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
Nach der Konfiguration:
|
||||||
|
|
||||||
|
1. Frontend öffnen: http://www.your-part.de
|
||||||
|
2. Auf "Login" oder Provider-Button klicken
|
||||||
|
3. Jeder verfügbare Provider sollte als Button angezeigt werden
|
||||||
|
4. Test: Mit jedem Provider einloggen
|
||||||
|
5. Test: Existender Nutzer → Einstellungen → Authentifizierung hinzufügen
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### "Invalid redirect URI"
|
||||||
|
- Stelle sicher, dass die Redirect URIs **exakt** übereinstimmen (inkl. `https://` vs `http://`)
|
||||||
|
- Beachte Trailing Slashes
|
||||||
|
|
||||||
|
### "Invalid client secret"
|
||||||
|
- Kopiere das Secret neu (nicht die ID)
|
||||||
|
- Manche Provider verstecken das Secret nach einmaliger Anzeige
|
||||||
|
|
||||||
|
### "Discovery endpoint not found"
|
||||||
|
- Überprüfe die Issuer URL (mit/ohne Trailing Slash)
|
||||||
|
- Für Keycloak: URL muss auf `/realms/xxx` enden
|
||||||
|
- Für ORY: URL darf nicht auf `/` enden
|
||||||
|
|
||||||
|
### Port-Konflikt lokal
|
||||||
|
- Keycloak benutzt `8080` → ändere auf: `docker run -p 8081:8080 ...`
|
||||||
|
- Stelle sicher, dass 3000 (Frontend) und 5000 (Backend) frei sind
|
||||||
|
|
||||||
0
PERFORMANCE_ANALYSIS.md
Normal file → Executable file
0
PERFORMANCE_ANALYSIS.md
Normal file → Executable file
3
README.md
Executable file
3
README.md
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
## zum testen des push
|
||||||
|
|
||||||
|
Hinweis: Das Verzeichnis **`src/`** (C++-Worker) ist veraltet; siehe [`docs/LEGACY_CPP_WORKERS.md`](docs/LEGACY_CPP_WORKERS.md).
|
||||||
0
README_MATCH3_CAMPAIGN.md
Normal file → Executable file
0
README_MATCH3_CAMPAIGN.md
Normal file → Executable file
0
SELL_OVERVIEW.md
Normal file → Executable file
0
SELL_OVERVIEW.md
Normal file → Executable file
168
SSL-SETUP.md
Executable file
168
SSL-SETUP.md
Executable file
@@ -0,0 +1,168 @@
|
|||||||
|
# SSL/TLS Setup für YourPart Daemon
|
||||||
|
|
||||||
|
Dieses Dokument beschreibt, wie Sie SSL/TLS-Zertifikate für den YourPart Daemon einrichten können.
|
||||||
|
|
||||||
|
## 🚀 Schnellstart
|
||||||
|
|
||||||
|
### 1. Self-Signed Certificate (Entwicklung/Testing)
|
||||||
|
```bash
|
||||||
|
./setup-ssl.sh
|
||||||
|
# Wählen Sie Option 1
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Let's Encrypt Certificate (Produktion)
|
||||||
|
```bash
|
||||||
|
./setup-ssl.sh
|
||||||
|
# Wählen Sie Option 2
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Apache2-Zertifikate verwenden (empfohlen für Ubuntu)
|
||||||
|
```bash
|
||||||
|
./setup-ssl.sh
|
||||||
|
# Wählen Sie Option 4
|
||||||
|
# Verwendet bereits vorhandene Apache2-Zertifikate
|
||||||
|
# ⚠️ Warnung bei Snakeoil-Zertifikaten (nur für localhost)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. DNS-01 Challenge (für komplexe Setups)
|
||||||
|
```bash
|
||||||
|
./setup-ssl-dns.sh
|
||||||
|
# Für Cloudflare, Route53, etc.
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📋 Voraussetzungen
|
||||||
|
|
||||||
|
### Für Apache2-Zertifikate:
|
||||||
|
- Apache2 installiert oder Zertifikate in Standard-Pfaden
|
||||||
|
- Unterstützte Pfade (priorisiert nach Qualität):
|
||||||
|
- `/etc/letsencrypt/live/your-part.de/fullchain.pem` (Let's Encrypt - empfohlen)
|
||||||
|
- `/etc/letsencrypt/live/$(hostname)/fullchain.pem` (Let's Encrypt)
|
||||||
|
- `/etc/apache2/ssl/apache.crt` (Custom Apache2)
|
||||||
|
- `/etc/ssl/certs/ssl-cert-snakeoil.pem` (Ubuntu Standard - nur localhost)
|
||||||
|
|
||||||
|
### Für Let's Encrypt (HTTP-01 Challenge):
|
||||||
|
- Port 80 muss verfügbar sein
|
||||||
|
- Domain `your-part.de` muss auf den Server zeigen
|
||||||
|
- Kein anderer Service auf Port 80
|
||||||
|
|
||||||
|
### Für DNS-01 Challenge:
|
||||||
|
- DNS-Provider Account (Cloudflare, Route53, etc.)
|
||||||
|
- API-Credentials für DNS-Management
|
||||||
|
|
||||||
|
## 🔧 Konfiguration
|
||||||
|
|
||||||
|
Nach der Zertifikats-Erstellung:
|
||||||
|
|
||||||
|
1. **SSL in der Konfiguration aktivieren:**
|
||||||
|
```ini
|
||||||
|
# /etc/yourpart/daemon.conf
|
||||||
|
WEBSOCKET_SSL_ENABLED=true
|
||||||
|
WEBSOCKET_SSL_CERT_PATH=/etc/yourpart/server.crt
|
||||||
|
WEBSOCKET_SSL_KEY_PATH=/etc/yourpart/server.key
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Daemon neu starten:**
|
||||||
|
```bash
|
||||||
|
sudo systemctl restart yourpart-daemon
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Verbindung testen:**
|
||||||
|
```bash
|
||||||
|
# WebSocket Secure
|
||||||
|
wss://your-part.de:4551
|
||||||
|
|
||||||
|
# Oder ohne SSL
|
||||||
|
ws://your-part.de:4551
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔄 Automatische Erneuerung
|
||||||
|
|
||||||
|
### Let's Encrypt-Zertifikate:
|
||||||
|
- **Cron Job:** Täglich um 2:30 Uhr
|
||||||
|
- **Script:** `/etc/yourpart/renew-ssl.sh`
|
||||||
|
- **Log:** `/var/log/yourpart/ssl-renewal.log`
|
||||||
|
|
||||||
|
### Apache2-Zertifikate:
|
||||||
|
- **Ubuntu Snakeoil:** Automatisch von Apache2 verwaltet
|
||||||
|
- **Let's Encrypt:** Automatische Erneuerung wenn erkannt
|
||||||
|
- **Custom:** Manuelle Verwaltung erforderlich
|
||||||
|
|
||||||
|
## 📁 Dateistruktur
|
||||||
|
|
||||||
|
```
|
||||||
|
/etc/yourpart/
|
||||||
|
├── server.crt # Zertifikat (Symlink zu Let's Encrypt)
|
||||||
|
├── server.key # Private Key (Symlink zu Let's Encrypt)
|
||||||
|
├── renew-ssl.sh # Auto-Renewal Script
|
||||||
|
└── cloudflare.ini # Cloudflare Credentials (falls verwendet)
|
||||||
|
|
||||||
|
/etc/letsencrypt/live/your-part.de/
|
||||||
|
├── fullchain.pem # Vollständige Zertifikatskette
|
||||||
|
├── privkey.pem # Private Key
|
||||||
|
├── cert.pem # Zertifikat
|
||||||
|
└── chain.pem # Intermediate Certificate
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🛠️ Troubleshooting
|
||||||
|
|
||||||
|
### Zertifikat wird nicht akzeptiert
|
||||||
|
```bash
|
||||||
|
# Prüfe Zertifikats-Gültigkeit
|
||||||
|
openssl x509 -in /etc/yourpart/server.crt -text -noout
|
||||||
|
|
||||||
|
# Prüfe Berechtigungen
|
||||||
|
ls -la /etc/yourpart/server.*
|
||||||
|
```
|
||||||
|
|
||||||
|
### Let's Encrypt Challenge fehlgeschlagen
|
||||||
|
```bash
|
||||||
|
# Prüfe Port 80
|
||||||
|
sudo netstat -tlnp | grep :80
|
||||||
|
|
||||||
|
# Prüfe DNS
|
||||||
|
nslookup your-part.de
|
||||||
|
|
||||||
|
# Prüfe Firewall
|
||||||
|
sudo ufw status
|
||||||
|
```
|
||||||
|
|
||||||
|
### Auto-Renewal funktioniert nicht
|
||||||
|
```bash
|
||||||
|
# Prüfe Cron Jobs
|
||||||
|
sudo crontab -l
|
||||||
|
|
||||||
|
# Teste Renewal Script
|
||||||
|
sudo /etc/yourpart/renew-ssl.sh
|
||||||
|
|
||||||
|
# Prüfe Logs
|
||||||
|
tail -f /var/log/yourpart/ssl-renewal.log
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔒 Sicherheit
|
||||||
|
|
||||||
|
### Berechtigungen
|
||||||
|
- **Zertifikat:** `644` (readable by all, writable by owner)
|
||||||
|
- **Private Key:** `600` (readable/writable by owner only)
|
||||||
|
- **Owner:** `yourpart:yourpart`
|
||||||
|
|
||||||
|
### Firewall
|
||||||
|
```bash
|
||||||
|
# Öffne Port 80 für Let's Encrypt Challenge
|
||||||
|
sudo ufw allow 80/tcp
|
||||||
|
|
||||||
|
# Öffne Port 4551 für WebSocket
|
||||||
|
sudo ufw allow 4551/tcp
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📚 Weitere Informationen
|
||||||
|
|
||||||
|
- [Let's Encrypt Dokumentation](https://letsencrypt.org/docs/)
|
||||||
|
- [Certbot Dokumentation](https://certbot.eff.org/docs/)
|
||||||
|
- [libwebsockets SSL](https://libwebsockets.org/lws-api-doc-master/html/group__ssl.html)
|
||||||
|
|
||||||
|
## 🆘 Support
|
||||||
|
|
||||||
|
Bei Problemen:
|
||||||
|
1. Prüfen Sie die Logs: `sudo journalctl -u yourpart-daemon -f`
|
||||||
|
2. Testen Sie die Zertifikate: `openssl s_client -connect your-part.de:4551`
|
||||||
|
3. Prüfen Sie die Firewall: `sudo ufw status`
|
||||||
9
android/.idea/android.iml
generated
Executable file
9
android/.idea/android.iml
generated
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="JAVA_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
2001
android/.idea/caches/deviceStreaming.xml
generated
Executable file
2001
android/.idea/caches/deviceStreaming.xml
generated
Executable file
File diff suppressed because it is too large
Load Diff
13
android/.idea/deviceManager.xml
generated
Executable file
13
android/.idea/deviceManager.xml
generated
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="DeviceTable">
|
||||||
|
<option name="columnSorters">
|
||||||
|
<list>
|
||||||
|
<ColumnSorterState>
|
||||||
|
<option name="column" value="Name" />
|
||||||
|
<option name="order" value="ASCENDING" />
|
||||||
|
</ColumnSorterState>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
8
android/.idea/markdown.xml
generated
Executable file
8
android/.idea/markdown.xml
generated
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="MarkdownSettings">
|
||||||
|
<option name="previewPanelProviderInfo">
|
||||||
|
<ProviderInfo name="Compose (experimental)" className="com.intellij.markdown.compose.preview.ComposePanelProvider" />
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
5
android/.idea/misc.xml
generated
Executable file
5
android/.idea/misc.xml
generated
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
<project version="4">
|
||||||
|
<component name="ProjectRootManager" version="2">
|
||||||
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
8
android/.idea/modules.xml
generated
Executable file
8
android/.idea/modules.xml
generated
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/android.iml" filepath="$PROJECT_DIR$/.idea/android.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
6
android/.idea/vcs.xml
generated
Executable file
6
android/.idea/vcs.xml
generated
Executable file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
605
android/ANDROID_APP_PLAN.md
Executable file
605
android/ANDROID_APP_PLAN.md
Executable file
@@ -0,0 +1,605 @@
|
|||||||
|
# Android-App-Plan fuer YourPart3
|
||||||
|
|
||||||
|
Stand: 2026-07-08
|
||||||
|
|
||||||
|
## Ziel
|
||||||
|
|
||||||
|
Dieses Dokument plant eine Android-App fuer das bestehende YourPart3-Projekt unter `/android`.
|
||||||
|
|
||||||
|
Das Projekt besteht aktuell aus:
|
||||||
|
|
||||||
|
- `frontend`: Vue 3, Vite, Vuetify, Vue Router, Vuex, Axios, Socket.IO Client, Three.js
|
||||||
|
- `backend`: Node.js/Express 5, Sequelize, Redis-Sessiondaten, OAuth/OIDC, Socket.IO, REST-APIs
|
||||||
|
- Authentifizierung: Login liefert einen User mit `id`/`authCode`; API-Requests senden Header `userid` und `authcode`
|
||||||
|
- Realtime: Socket.IO fuer Backend-Events und separater Daemon-WebSocket fuer Falukant-Updates
|
||||||
|
- Deployment: Backend serviert die gebaute SPA aus `frontend/dist`
|
||||||
|
|
||||||
|
Backend-Implementierung ist nicht Teil dieses Android-Starts. Das vorhandene Backend wird als gegeben betrachtet; Android-seitig werden nur Kompatibilitaet, URLs, Auth-Header, OAuth-Weiterleitung und Realtime-Verbindungen getestet.
|
||||||
|
|
||||||
|
## Empfehlung
|
||||||
|
|
||||||
|
Die Android-App sollte in Phase 1 als Capacitor-App umgesetzt werden, nicht als nativer Rewrite.
|
||||||
|
|
||||||
|
Begruendung:
|
||||||
|
|
||||||
|
- Die bestehende App ist bereits eine grosse SPA mit vielen Views: Social Network, Falukant, Vokabeltrainer, Minigames, Kalender, Admin, Settings.
|
||||||
|
- Der Auth-Mechanismus und die vorhandenen API-Clients sind Web-orientiert und koennen in einer WebView nahezu unveraendert weiterlaufen.
|
||||||
|
- OAuth-Callback-Routen existieren bereits im Frontend (`/auth/oauth/callback`, `/auth/oauth/user/callback`).
|
||||||
|
- Socket.IO und WebSocket-Verbindungen funktionieren in Capacitor deutlich schneller als in einem nativen Rewrite.
|
||||||
|
- Ein nativer Rewrite wuerde zuerst API-Vertraege, Sessionmodell, Navigation, Offline-Strategie und UI-Komponenten neu definieren muessen.
|
||||||
|
|
||||||
|
Zielarchitektur Phase 1:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/android
|
||||||
|
capacitor.config.ts
|
||||||
|
package.json
|
||||||
|
android/
|
||||||
|
Android-native Projektdateien, durch Capacitor generiert
|
||||||
|
|
||||||
|
/frontend
|
||||||
|
bestehende Vue/Vite-App
|
||||||
|
|
||||||
|
/backend
|
||||||
|
bestehende Express/API/Socket.IO-App
|
||||||
|
```
|
||||||
|
|
||||||
|
Capacitor verwendet den bestehenden `frontend`-Build als Web-Bundle und erzeugt daraus eine installierbare Android-App.
|
||||||
|
|
||||||
|
## Nicht-Ziele fuer Phase 1
|
||||||
|
|
||||||
|
- Kein kompletter nativer Kotlin/Jetpack-Compose-Rewrite.
|
||||||
|
- Keine Offline-First-Synchronisation fuer Falukant/Social/Vocab.
|
||||||
|
- Keine komplette Neugestaltung aller mobilen Screens.
|
||||||
|
- Keine API-Versionierung fuer mobile Clients, solange die App nur das bestehende Web-Frontend verpackt.
|
||||||
|
- Keine Play-Store-Verteilung vor Datenschutz-, Content- und OAuth-Pruefung.
|
||||||
|
- Keine Backend-Neuentwicklung und keine Backend-API-Neuplanung.
|
||||||
|
|
||||||
|
## Getroffene Entscheidungen
|
||||||
|
|
||||||
|
### App-Technologie
|
||||||
|
|
||||||
|
- Entscheidung: Capacitor mit lokal gebuendelter Vue/Vite-App.
|
||||||
|
- Kein nativer Kotlin-Rewrite in Phase 1.
|
||||||
|
- Kein reiner Remote-WebView-Wrapper auf `https://www.your-part.de`.
|
||||||
|
- Begruendung: Der vorhandene Funktionsumfang ist breit, Web-Auth und Socket.IO existieren bereits, und Capacitor ermoeglicht spaetere native Erweiterungen ohne sofortigen Rewrite.
|
||||||
|
|
||||||
|
### App-ID und Name
|
||||||
|
|
||||||
|
- App-ID: `de.yourpart.app`
|
||||||
|
- Launcher-Name: `YourPart`
|
||||||
|
- Android-Projektpfad: `/android`
|
||||||
|
- Capacitor `webDir`: `../frontend/dist`
|
||||||
|
|
||||||
|
### Ziel-Distribution
|
||||||
|
|
||||||
|
- Phase 1: interne Debug-/Test-APK.
|
||||||
|
- Phase 2: signiertes internes AAB/APK fuer Testgeraete.
|
||||||
|
- Play Store erst nach separatem Compliance-Check fuer Datenschutz, UGC, Moderation und Adult Content.
|
||||||
|
|
||||||
|
### Backend-Abgrenzung
|
||||||
|
|
||||||
|
- Backend bleibt unveraendert.
|
||||||
|
- Android nutzt die bestehenden REST-Endpunkte, Auth-Header, OAuth-Routen, Socket.IO-Events und Daemon-WebSocket-Events.
|
||||||
|
- Backendbezogene TODOs sind nur Test- und Konfigurationschecks. Falls ein Test scheitert, wird der konkrete Anpassungsbedarf danach separat entschieden.
|
||||||
|
|
||||||
|
### Admin-Bereich
|
||||||
|
|
||||||
|
- Admin-Routen bleiben in Phase 1 nicht priorisiert.
|
||||||
|
- Wenn Admin-Menues durch bestehende Berechtigungen sichtbar sind, werden sie nicht aktiv entfernt.
|
||||||
|
- Abnahmekriterien fuer Phase 1 gelten nur fuer normale Nutzerfunktionen.
|
||||||
|
|
||||||
|
### Adult-/Erotikbereiche
|
||||||
|
|
||||||
|
- Phase 1: vorhandenes Web-Gating bleibt bestehen, keine neue native Adult-Content-Funktion.
|
||||||
|
- Play-Store-Ziel ist blockiert, bis Altersfreigabe, UGC-Moderation, Melden/Blockieren, Datenschutz und Store-Policy separat geprueft sind.
|
||||||
|
- Fuer interne APK-Tests darf der Bereich technisch erreichbar bleiben, wenn der bestehende Account-/Altersstatus ihn erlaubt.
|
||||||
|
|
||||||
|
### OAuth
|
||||||
|
|
||||||
|
- Phase 1 startet mit Username/Passwort-Login als Pflichtfunktion.
|
||||||
|
- OAuth ist Phase-1-Testumfang, aber kein Blocker fuer das erste Debug-APK.
|
||||||
|
- Zielrichtung fuer OAuth: externer Browser bzw. System-Browser plus App Links, nicht OAuth in einer versteckten WebView erzwingen.
|
||||||
|
|
||||||
|
### Push Notifications
|
||||||
|
|
||||||
|
- Push ist nicht Teil des ersten Android-Scaffolds.
|
||||||
|
- Push wird nach stabiler App-Shell geplant, weil dafuer Device Tokens, Opt-in, Settings und Backend-Zustellung noetig sind.
|
||||||
|
|
||||||
|
### 3D / WebGL
|
||||||
|
|
||||||
|
- 3D-Charaktere werden im Android-Debug-Build initial per `VITE_DISABLE_3D=true` deaktiviert.
|
||||||
|
- Begruendung: Die Login-Seite rendert mehrere `Character3D`-Instanzen sofort. In Kombination mit CORS-Fehlern und vielen GLB-Kandidaten kann der Emulator-WebView-Renderer per OOM abstuerzen.
|
||||||
|
- Reaktivierung erfolgt erst nach erfolgreichem CORS-Test und separatem 3D-Performance-Test.
|
||||||
|
|
||||||
|
### Navigation
|
||||||
|
|
||||||
|
- Vue `createWebHistory` bleibt initial unveraendert.
|
||||||
|
- Hash-Routing wird nur eingefuehrt, wenn Capacitor-Tests echte Routing-Probleme zeigen.
|
||||||
|
- Android Back Button wird als native App-Anforderung in Phase 1 umgesetzt.
|
||||||
|
- Mobile Navigation bleibt Teil der Web-App, wird aber fuer Android als kompakte Hybrid-Navigation gehaertet: Header-Leiste, aufklappbares scrollbares Menue, keine dauerhaft sichtbare Desktop-Menueflaeche auf kleinen Displays.
|
||||||
|
|
||||||
|
### Sichere Speicherung
|
||||||
|
|
||||||
|
- Phase 1 darf bestehendes `localStorage`/`sessionStorage` weiterverwenden.
|
||||||
|
- Vor Play-Store-Release wird Auth-Persistenz auf Secure Storage/Android Keystore umgestellt.
|
||||||
|
|
||||||
|
## Technische Ausgangslage
|
||||||
|
|
||||||
|
### Frontend
|
||||||
|
|
||||||
|
- Zentrale API-Konfiguration: `frontend/src/utils/axios.js`
|
||||||
|
- API-Basis-URL: `frontend/src/utils/appConfig.js` ueber `VITE_API_BASE_URL`
|
||||||
|
- Auth-Header: `userid` und `authcode`
|
||||||
|
- Persistenz: `localStorage` oder `sessionStorage` fuer `isLoggedIn`, `user`, `userid`
|
||||||
|
- Router: `createWebHistory`, viele Clean-URL-Routen
|
||||||
|
- Realtime: `socket.io-client` ueber `VITE_SOCKET_IO_URL`
|
||||||
|
- Daemon-WebSocket: ueber `VITE_DAEMON_SOCKET`
|
||||||
|
- 3D/Assets: Three.js und Modelle ueber `/api/models` bzw. statische Assets
|
||||||
|
|
||||||
|
### Backend
|
||||||
|
|
||||||
|
- CORS erlaubt aktuell konfigurierte Origins und lokale Web-Origins.
|
||||||
|
- Auth-Middleware prueft `userid` und `authcode`.
|
||||||
|
- OAuth startet serverseitig per Redirect.
|
||||||
|
- Socket.IO erlaubt aktuell `origin: '*'`.
|
||||||
|
- Backend serviert SPA-Fallback fuer Nicht-API-Routen.
|
||||||
|
|
||||||
|
## Android-Strategie
|
||||||
|
|
||||||
|
### Phase 1: Capacitor Shell
|
||||||
|
|
||||||
|
Die Android-App laedt nicht die Produktionswebsite remote, sondern nutzt das lokal gebundelte Vite-Build-Artefakt.
|
||||||
|
|
||||||
|
Vorteile:
|
||||||
|
|
||||||
|
- App startet auch dann, wenn die Website selbst nicht als Web-Seite geladen werden muss.
|
||||||
|
- Google Play bewertet sie eher als App statt als reinen Browser-Shortcut.
|
||||||
|
- Versionierbare Builds mit reproduzierbarer Web-Bundle-Version.
|
||||||
|
- Zugriff auf native Funktionen bleibt moeglich: Splash Screen, Deep Links, Push Notifications, sichere Speicherung.
|
||||||
|
|
||||||
|
Wichtige Anpassung:
|
||||||
|
|
||||||
|
- `VITE_API_BASE_URL`, `VITE_SOCKET_IO_URL`, `VITE_DAEMON_SOCKET` muessen fuer Android-Builds explizit auf die produktiven HTTPS/WSS-Endpunkte gesetzt werden.
|
||||||
|
- Relative API-URLs sind in einer gebuendelten Android-WebView riskant, weil `window.location.origin` nicht der Server-Origin ist.
|
||||||
|
|
||||||
|
### Phase 2: Mobile Web-Haertung
|
||||||
|
|
||||||
|
Die bestehende UI muss fuer kleine Viewports und Touch-Nutzung stabilisiert werden.
|
||||||
|
|
||||||
|
Prioritaeten:
|
||||||
|
|
||||||
|
- Login/Register/OAuth
|
||||||
|
- Hauptnavigation
|
||||||
|
- Falukant-Overview, Branch, Family, Bank
|
||||||
|
- Vokabeltrainer und Lessons
|
||||||
|
- Chat/Friends/Forum-Basics
|
||||||
|
- Minigames nur nach separater Touch-Performance-Pruefung
|
||||||
|
|
||||||
|
### Phase 3: Native Integrationen
|
||||||
|
|
||||||
|
Nach stabiler Shell koennen echte App-Features ergaenzt werden:
|
||||||
|
|
||||||
|
- Push Notifications fuer Chat, Freund-Login, Falukant-Events
|
||||||
|
- Deep Links fuer OAuth-Callbacks und geteilte Inhalte
|
||||||
|
- Android Back Button Integration
|
||||||
|
- Splash Screen und App Icons
|
||||||
|
- Secure Storage fuer Authdaten
|
||||||
|
- App Update / Version Check
|
||||||
|
|
||||||
|
### Phase 4: Selektiv native Screens
|
||||||
|
|
||||||
|
Wenn einzelne Bereiche Performance- oder UX-Probleme haben, koennen sie spaeter nativ ersetzt werden. Kandidaten:
|
||||||
|
|
||||||
|
- Login/Onboarding
|
||||||
|
- Push Notification Center
|
||||||
|
- Vokabeltrainer Session
|
||||||
|
- Falukant Status/Quick Actions
|
||||||
|
|
||||||
|
## Repository-Layout
|
||||||
|
|
||||||
|
Vorgeschlagenes Layout:
|
||||||
|
|
||||||
|
```text
|
||||||
|
android/
|
||||||
|
ANDROID_APP_PLAN.md
|
||||||
|
README.md
|
||||||
|
package.json
|
||||||
|
capacitor.config.ts
|
||||||
|
android/ # Capacitor Android-Projekt
|
||||||
|
scripts/
|
||||||
|
build-android-web.sh
|
||||||
|
sync-android.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Hinweis: In Phase 1 wird `/android/android` generiert, weil `/android` die Capacitor-Projektwurzel ist. Die generierten Android-Dateien werden versioniert, weil reproduzierbare Builds und native Anpassungen wichtig sind.
|
||||||
|
|
||||||
|
## Build-Konzept
|
||||||
|
|
||||||
|
### Android Web-Build
|
||||||
|
|
||||||
|
Ein eigener Build-Modus verhindert Vermischung mit Web-Production:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd frontend
|
||||||
|
npm run build -- --mode android
|
||||||
|
```
|
||||||
|
|
||||||
|
Dafuer wird eine Datei `frontend/.env.android` benoetigt:
|
||||||
|
|
||||||
|
```env
|
||||||
|
VITE_API_BASE_URL=https://www.your-part.de
|
||||||
|
VITE_SOCKET_IO_URL=https://www.your-part.de
|
||||||
|
VITE_DAEMON_SOCKET=wss://www.your-part.de
|
||||||
|
VITE_PUBLIC_BASE_URL=https://www.your-part.de
|
||||||
|
```
|
||||||
|
|
||||||
|
Wichtig: `VITE_API_BASE_URL` ist bewusst nur die Origin ohne `/api`, weil die bestehenden Frontend-Aufrufe bereits Pfade wie `/api/auth/login` enthalten. Mit `/api` in der Base-URL entstehen Android-seitig falsche Requests wie `/api/api/...`.
|
||||||
|
|
||||||
|
Die exakten WebSocket-Pfade muessen gegen die produktive Apache-/Backend-Konfiguration verifiziert werden.
|
||||||
|
|
||||||
|
### Lokaler Emulator-Stand
|
||||||
|
|
||||||
|
Android Studio und mehrere AVDs sind lokal vorhanden. Fuer die ersten Stabilitaetstests ist `trainingstagebuchApi35` die bevorzugte VM, weil sie im bisherigen Test stabiler lief als das Play-Store-Image `Medium_Phone`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ANDROID_AVD_HOME=/home/torsten/.config/.android/avd /home/torsten/Android/Sdk/emulator/emulator -avd trainingstagebuchApi35 -no-snapshot-save
|
||||||
|
adb install -r android/android/app/build/outputs/apk/debug/app-debug.apk
|
||||||
|
adb shell am start -W -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -n de.yourpart.app/.MainActivity
|
||||||
|
```
|
||||||
|
|
||||||
|
Ergebnis bisher:
|
||||||
|
|
||||||
|
- Debug-APK wurde erfolgreich gebaut.
|
||||||
|
- APK wurde auf einem Emulator installiert.
|
||||||
|
- App startet als `de.yourpart.app/.MainActivity`.
|
||||||
|
- Login-Screen rendert mobil.
|
||||||
|
- API-Base-URL wurde von `/api` auf die Origin `https://www.your-part.de` korrigiert, damit keine `/api/api`-Requests entstehen.
|
||||||
|
- Capacitor `server.hostname` darf nicht auf `www.your-part.de` gesetzt werden, weil sonst echte Backend- und Model-URLs als lokale App-Assets behandelt werden.
|
||||||
|
- Nach Entfernung der Hostname-Kollision ist die Android-App-Origin `https://localhost`. Das Backend muss diese Origin in `CORS_ORIGINS` erlauben, sonst blockiert die WebView REST- und GLB-Requests.
|
||||||
|
|
||||||
|
### Capacitor Sync
|
||||||
|
|
||||||
|
Nach dem Frontend-Build:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd android
|
||||||
|
npx cap sync android
|
||||||
|
```
|
||||||
|
|
||||||
|
Danach:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd android
|
||||||
|
npx cap open android
|
||||||
|
```
|
||||||
|
|
||||||
|
Oder per CLI:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd android
|
||||||
|
./gradlew assembleDebug
|
||||||
|
```
|
||||||
|
|
||||||
|
Lokaler Build-Hinweis:
|
||||||
|
|
||||||
|
- Auf diesem System liegt das Android SDK unter `/home/torsten/Android/Sdk`.
|
||||||
|
- Die lokale Datei `/android/android/local.properties` setzt `sdk.dir` darauf und ist absichtlich nicht versioniert.
|
||||||
|
- Erstes Debug-APK wurde erfolgreich gebaut: `/android/android/app/build/outputs/apk/debug/app-debug.apk`.
|
||||||
|
|
||||||
|
## Authentifizierung
|
||||||
|
|
||||||
|
### Bestehender Login
|
||||||
|
|
||||||
|
Der bestehende Login kann initial unveraendert bleiben:
|
||||||
|
|
||||||
|
- `POST /api/auth/login`
|
||||||
|
- Antwort enthaelt User inkl. `authCode`
|
||||||
|
- Axios haengt `userid` und `authcode` an Folgerequests
|
||||||
|
- Storage bleibt vorerst `localStorage`/`sessionStorage`
|
||||||
|
|
||||||
|
### Sicherheitsverbesserung
|
||||||
|
|
||||||
|
Phase 1 kann noch mit Web Storage starten. Vor Play-Store-Release sollte Auth aber in native sichere Speicherung verschoben werden:
|
||||||
|
|
||||||
|
- Capacitor Preferences nur fuer unkritische Werte
|
||||||
|
- Fuer sensible Werte besser Android Keystore ueber ein Secure-Storage-Plugin
|
||||||
|
- Migration: Store liest zuerst Secure Storage, fallback auf lokalen Web Storage, migriert dann
|
||||||
|
|
||||||
|
### OAuth
|
||||||
|
|
||||||
|
OAuth ist der groesste Integrationspunkt.
|
||||||
|
|
||||||
|
Kurzfristige Option:
|
||||||
|
|
||||||
|
- OAuth im In-App Browser oder externen Browser starten
|
||||||
|
- Callback bleibt auf `https://www.your-part.de/auth/oauth/callback`
|
||||||
|
- Die Callback-Seite tauscht `code/state` wie bisher gegen einen App-User
|
||||||
|
|
||||||
|
Bessere App-Option:
|
||||||
|
|
||||||
|
- Android App Links fuer `https://www.your-part.de/auth/oauth/callback`
|
||||||
|
- `assetlinks.json` auf der Domain bereitstellen
|
||||||
|
- Capacitor App Plugin verarbeitet den Deep Link und routet intern weiter
|
||||||
|
|
||||||
|
Risiko:
|
||||||
|
|
||||||
|
- OAuth Provider koennen eingebettete WebViews einschraenken. Deshalb sollte OAuth nicht in einer versteckten WebView erzwungen werden, sondern ueber Browser/App Links laufen.
|
||||||
|
|
||||||
|
## API und CORS
|
||||||
|
|
||||||
|
Fuer Capacitor-Bundles ist die Origin nicht immer identisch mit der Website-Origin.
|
||||||
|
|
||||||
|
Zu pruefen:
|
||||||
|
|
||||||
|
- Welche Origin sendet Android WebView bei Requests an `https://www.your-part.de/api`?
|
||||||
|
- Muss `CORS_ORIGINS` um `https://localhost` erweitert werden?
|
||||||
|
- Funktionieren Custom Header `userid` und `authcode` in der WebView?
|
||||||
|
- Funktionieren Preflight-Requests mit den bestehenden erlaubten Headers?
|
||||||
|
|
||||||
|
Noetige Backend-Konfiguration fuer Debug-Builds:
|
||||||
|
|
||||||
|
```env
|
||||||
|
CORS_ORIGINS=https://www.your-part.de,https://localhost,http://localhost:5173,http://127.0.0.1:5173
|
||||||
|
```
|
||||||
|
|
||||||
|
Nur nach Test setzen; nicht blind `CORS_ALLOW_ALL=1` fuer Produktion verwenden.
|
||||||
|
|
||||||
|
## Navigation und Deep Links
|
||||||
|
|
||||||
|
Die Vue-App nutzt `createWebHistory`. In Capacitor kann das funktionieren, aber folgende Punkte muessen getestet werden:
|
||||||
|
|
||||||
|
- Direktstart auf `/`
|
||||||
|
- Interne Navigation zu `/falukant/home`, `/friends`, `/socialnetwork/vocab/...`
|
||||||
|
- Android Back Button
|
||||||
|
- OAuth Callback URL
|
||||||
|
- App-Resume nach Browser-OAuth
|
||||||
|
|
||||||
|
Falls History-Mode Probleme in der WebView macht:
|
||||||
|
|
||||||
|
- Option A: Capacitor-spezifisch auf Hash-History wechseln
|
||||||
|
- Option B: History beibehalten und Deep-Link-Routing sauber behandeln
|
||||||
|
|
||||||
|
Hash-History waere technisch einfacher, aber wegen bestehender SEO-/Web-Routen nicht global fuer das Web-Frontend umstellen.
|
||||||
|
|
||||||
|
## Realtime
|
||||||
|
|
||||||
|
### Socket.IO
|
||||||
|
|
||||||
|
Bestehender Ablauf:
|
||||||
|
|
||||||
|
- Nach Login `initializeSocket`
|
||||||
|
- Socket verbindet zu `VITE_SOCKET_IO_URL`
|
||||||
|
- Client sendet `setUserId` mit `hashedId` oder `id`
|
||||||
|
|
||||||
|
Android-Testfaelle:
|
||||||
|
|
||||||
|
- Login erzeugt Socket-Verbindung
|
||||||
|
- App im Hintergrund trennt/reconnectet sauber
|
||||||
|
- Friend-Login-Events kommen an
|
||||||
|
- Schlechte Verbindung erzeugt keine Endlos-Fehlerdialoge
|
||||||
|
|
||||||
|
### Daemon-WebSocket
|
||||||
|
|
||||||
|
Falukant nutzt zusaetzliche Daemon-Events. Android muss mindestens diese Events empfangen koennen:
|
||||||
|
|
||||||
|
- `falukantUpdateFamily`
|
||||||
|
- `falukantUpdateStatus`
|
||||||
|
- `falukantUpdateProductionCertificate`
|
||||||
|
- `children_update`
|
||||||
|
- `falukantUpdateChurch`
|
||||||
|
- `falukantUpdateDebt`
|
||||||
|
|
||||||
|
Test:
|
||||||
|
|
||||||
|
- WSS ueber produktiven Proxy
|
||||||
|
- Reconnect nach App-Resume
|
||||||
|
- Filterung nach `user_id`
|
||||||
|
|
||||||
|
## Mobile UX Prioritaeten
|
||||||
|
|
||||||
|
Die App sollte nicht nur ein Desktop-Layout in einer WebView zeigen. Phase 1 braucht mindestens diese UX-Haertung:
|
||||||
|
|
||||||
|
- Header/Navigation auf kleinen Viewports pruefen
|
||||||
|
- Dialoge auf 360px Breite testen
|
||||||
|
- Tabellen und breite Falukant-Views horizontal oder responsiv absichern
|
||||||
|
- Touch-Ziele mindestens ca. 44px
|
||||||
|
- Keyboard-Verhalten im Login/Register testen
|
||||||
|
- Safe Area Insets fuer Statusbar/Navigationbar beachten
|
||||||
|
- Android Back Button: Dialog schliessen, sonst Router zurueck, sonst App minimieren
|
||||||
|
|
||||||
|
Aktueller Stand 2026-07-08:
|
||||||
|
|
||||||
|
- Hauptnavigation ist auf kleinen Viewports zu einer kompakten Menueleiste mit aufklappbarem, scrollbarem Menue umgebaut.
|
||||||
|
- Header ist auf Smartphone-Breite kompakter, Statusanzeigen laufen zweispaltig statt als lange Desktop-Leiste.
|
||||||
|
- Footer blendet leere System-/Fensterbereiche auf Smartphone-Breite aus und reserviert Safe-Area-Abstand nach unten.
|
||||||
|
- App-Shell nutzt `100dvh` als Android-WebView-freundlichere Viewport-Hoehe.
|
||||||
|
|
||||||
|
## Datenschutz, Content und Store-Risiken
|
||||||
|
|
||||||
|
Das Projekt enthaelt Social-, Chat-, Galerie-, Erotik-/Adult- und Moderationsbereiche. Fuer Play Store sind diese Punkte kritisch:
|
||||||
|
|
||||||
|
- Altersfreigabe und Adult-Content-Gating
|
||||||
|
- UGC-Moderation, Meldefunktion, Blockieren
|
||||||
|
- Datenschutzrichtlinie in der App und im Store Listing
|
||||||
|
- Account-Loeschung oder klare Anleitung
|
||||||
|
- Sichere Uebertragung nur per HTTPS/WSS
|
||||||
|
- Keine unsicheren Debug-Endpunkte im Release-Build
|
||||||
|
- Keine Secrets im Android-Bundle
|
||||||
|
|
||||||
|
Vor Play-Store-Release muss ein eigener Compliance-Check erfolgen.
|
||||||
|
|
||||||
|
## Teststrategie
|
||||||
|
|
||||||
|
### Lokale Tests
|
||||||
|
|
||||||
|
- Android Emulator mit Debug-Build
|
||||||
|
- Echtes Android-Geraet im gleichen Netz
|
||||||
|
- Produktions-API mit Testnutzer
|
||||||
|
- Offline/Online-Wechsel
|
||||||
|
- App Kill/Restart/Resume
|
||||||
|
|
||||||
|
### Kern-Testmatrix
|
||||||
|
|
||||||
|
- Login mit Username/Passwort
|
||||||
|
- Logout
|
||||||
|
- Registrierung
|
||||||
|
- Passwort vergessen
|
||||||
|
- OAuth Login je Provider, soweit konfiguriert
|
||||||
|
- Menu-Load nach Login
|
||||||
|
- Falukant Overview laden
|
||||||
|
- Falukant Realtime-Update empfangen
|
||||||
|
- Vokabeltrainer Lesson starten und abschliessen
|
||||||
|
- Chat verbinden und Nachricht empfangen
|
||||||
|
- Galerie/Bild-Upload, falls mobil zunaechst erlaubt
|
||||||
|
- Minigames Touch-Steuerung
|
||||||
|
- Admin-Bereiche entweder nutzbar oder bewusst ausgeblendet
|
||||||
|
|
||||||
|
### Build-Checks
|
||||||
|
|
||||||
|
- `npm run build` im Frontend
|
||||||
|
- Android Web-Build mit `.env.android`
|
||||||
|
- `npx cap sync android`
|
||||||
|
- `./gradlew assembleDebug`
|
||||||
|
- `./gradlew lint`
|
||||||
|
- Release-Build mit Signing-Konfiguration
|
||||||
|
|
||||||
|
## Verbleibende offene Punkte
|
||||||
|
|
||||||
|
- Produktivdomain final technisch testen: voraussichtlich `https://www.your-part.de`.
|
||||||
|
- Daemon-WebSocket-URL und Pfad final gegen Deploy-/Proxy-Konfiguration testen.
|
||||||
|
- Mindest-Android-Version aus Capacitor-Default uebernehmen und nach erstem Scaffold im Gradle-Projekt dokumentieren.
|
||||||
|
- Play-Store-Entscheidung bleibt nachgelagert bis Compliance-Pruefung abgeschlossen ist.
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
### 1. Grundsatzentscheidungen
|
||||||
|
|
||||||
|
- [x] App-ID festlegen: `de.yourpart.app`.
|
||||||
|
- [x] App-Name und Launcher-Label festlegen: `YourPart`.
|
||||||
|
- [x] Ziel-Distribution festlegen: zuerst interne Debug-/Test-APK.
|
||||||
|
- [x] Entscheiden, ob Admin-Routen in der App sichtbar bleiben: nicht priorisiert, nicht aktiv entfernt.
|
||||||
|
- [x] Entscheiden, wie Adult-/Erotikbereiche in Android behandelt werden: bestehendes Web-Gating, kein Play Store ohne Compliance-Check.
|
||||||
|
- [x] Entscheiden, ob Backend Teil des Android-Starts ist: nein, nur Kompatibilitaetstests.
|
||||||
|
- [x] Entscheiden, ob Push Teil des ersten Scaffolds ist: nein.
|
||||||
|
- [x] Entscheiden, ob OAuth erster Blocker ist: nein, Username/Passwort-Login zuerst.
|
||||||
|
|
||||||
|
### 2. Android-Projekt scaffolden
|
||||||
|
|
||||||
|
- [x] In `/android` eigenes `package.json` anlegen.
|
||||||
|
- [x] Capacitor installieren: `@capacitor/core`, `@capacitor/cli`, `@capacitor/android`.
|
||||||
|
- [x] `capacitor.config.ts` mit App-ID `de.yourpart.app`, App-Name `YourPart` und `webDir` auf `../frontend/dist` konfigurieren.
|
||||||
|
- [x] Android-Plattform generieren: `npx cap add android`.
|
||||||
|
- [x] `/android/README.md` mit Build-Kommandos anlegen.
|
||||||
|
- [x] Entscheiden, ob generiertes `/android/android` versioniert wird: ja.
|
||||||
|
|
||||||
|
### 3. Frontend Android-Build
|
||||||
|
|
||||||
|
- [x] `frontend/.env.android.example` anlegen.
|
||||||
|
- [x] `VITE_API_BASE_URL` fuer Android explizit setzen.
|
||||||
|
- [x] `VITE_SOCKET_IO_URL` fuer Android explizit setzen.
|
||||||
|
- [x] `VITE_DAEMON_SOCKET` fuer Android explizit setzen.
|
||||||
|
- [x] Root- oder Android-Script fuer `build:android:web` ergaenzen.
|
||||||
|
- [x] Android-Web-Build mit produktiver Origin statt lokaler Dev-URL bauen.
|
||||||
|
- [ ] Release-Build-Gate ergaenzen, das lokale Dev-URLs automatisiert verhindert.
|
||||||
|
|
||||||
|
### 4. Backend-Kompatibilitaet
|
||||||
|
|
||||||
|
- [ ] Android-Origin im CORS-Verhalten messen.
|
||||||
|
- [x] Fehlerhafte Android-Request-Basis `/api/api` identifizieren und durch Origin-only-Config beheben.
|
||||||
|
- [x] Capacitor-Hostname-Kollision mit Backend-Host vermeiden; `server.hostname` bleibt Default.
|
||||||
|
- [x] `CORS_ORIGINS` fuer Capacitor als bestehenden Backend-Konfigurationspunkt notieren: `https://localhost`.
|
||||||
|
- [ ] Produktiv-/Testbackend mit `CORS_ORIGINS` inklusive `https://localhost` neu starten und Android-Requests erneut pruefen.
|
||||||
|
- [ ] Custom Header `userid`/`authcode` auf Android testen.
|
||||||
|
- [ ] Socket.IO-Verbindung von Android testen.
|
||||||
|
- [ ] Daemon-WebSocket ueber Android testen.
|
||||||
|
- [ ] Produktionsproxy fuer HTTPS/WSS pruefen.
|
||||||
|
- [ ] Keine Backend-Aenderung ohne konkreten fehlgeschlagenen Android-Test einplanen.
|
||||||
|
|
||||||
|
### 5. Auth und OAuth
|
||||||
|
|
||||||
|
- [ ] Username/Passwort-Login in Android testen.
|
||||||
|
- [ ] Persistenz nach App-Neustart testen.
|
||||||
|
- [ ] Logout inklusive Socket-Cleanup testen.
|
||||||
|
- [ ] OAuth-Login-Flow je Provider testen.
|
||||||
|
- [ ] Entscheiden: OAuth per externem Browser plus App Links oder innerhalb bestehender WebView.
|
||||||
|
- [ ] Android App Links einrichten, falls OAuth nativ zurueck in die App fuehren soll.
|
||||||
|
- [ ] Authdaten spaeter in Secure Storage migrieren.
|
||||||
|
|
||||||
|
### 6. Native App-Verhalten
|
||||||
|
|
||||||
|
- [ ] Android Back Button behandeln.
|
||||||
|
- [ ] Splash Screen konfigurieren.
|
||||||
|
- [ ] App Icons erzeugen.
|
||||||
|
- [ ] Statusbar/Safe-Area pruefen; aktueller Test zeigt nicht-blockierende Safe-Area-CSS-Console-Fehler.
|
||||||
|
- [x] WebView-Textfeld-Eingabe fuer Emulator reparieren: `android.captureInput` nicht aktivieren.
|
||||||
|
- [x] Android-Studio-Projektpfad dokumentieren: `/android/android`.
|
||||||
|
- [x] Android-Studio-Run-Configuration `YourPart Debug` anlegen.
|
||||||
|
- [ ] Deep-Link-Handling vorbereiten.
|
||||||
|
- [ ] App Resume/Pause Events fuer Socket-Reconnect nutzen.
|
||||||
|
|
||||||
|
### 7. Mobile UI-Haertung
|
||||||
|
|
||||||
|
- [ ] Login/Register auf 360px Breite testen.
|
||||||
|
- [x] Login-Screen im Emulator visuell pruefen.
|
||||||
|
- [x] Parameterlisten-Handling gegen Nicht-Array-Antworten haerten, damit Backend-Fehler keine UI-Exception ausloesen.
|
||||||
|
- [x] 3D-Modelle fuer Android-Debug per `VITE_DISABLE_3D=true` deaktivieren, damit Login/Onboarding stabil bleibt.
|
||||||
|
- [x] Hauptnavigation fuer kleine Viewports umbauen: kompakte Menueleiste plus scrollbares Menue statt voller Desktop-Navigation.
|
||||||
|
- [ ] Hauptnavigation mobil mit mehreren Rollen/Berechtigungssets testen.
|
||||||
|
- [ ] Dialoge auf kleinen Screens pruefen.
|
||||||
|
- [ ] Falukant-Views mit breiten Tabellen pruefen.
|
||||||
|
- [ ] Vokabeltrainer Touch- und Keyboard-Verhalten testen.
|
||||||
|
- [ ] Minigames separat auf Touch-Performance testen.
|
||||||
|
- [ ] Bild-/Dateiupload auf Android pruefen.
|
||||||
|
|
||||||
|
### 8. Push Notifications
|
||||||
|
|
||||||
|
- [ ] Entscheiden, ob Push in Phase 1 oder spaeter kommt.
|
||||||
|
- [ ] Event-Kandidaten definieren: Chat, Friend Login, Falukant, Vocab Reminder.
|
||||||
|
- [ ] Backend-Device-Token-Modell planen.
|
||||||
|
- [ ] FCM-Projekt konfigurieren.
|
||||||
|
- [ ] Opt-in und Settings-UI planen.
|
||||||
|
|
||||||
|
### 9. Store/Compliance
|
||||||
|
|
||||||
|
- [ ] Datenschutzseite in App erreichbar machen.
|
||||||
|
- [ ] Impressum in App erreichbar machen.
|
||||||
|
- [ ] Account-Loeschung/Anfrageprozess klaeren.
|
||||||
|
- [ ] Adult Content Policy pruefen.
|
||||||
|
- [ ] UGC-Moderation fuer Store Review dokumentieren.
|
||||||
|
- [ ] Release-Build ohne Debug-Konfiguration pruefen.
|
||||||
|
|
||||||
|
### 10. CI/CD
|
||||||
|
|
||||||
|
- [x] Android-Build-Script anlegen.
|
||||||
|
- [x] Debug-Build lokal reproduzierbar machen.
|
||||||
|
- [ ] Release-Signing-Konzept festlegen.
|
||||||
|
- [ ] Keystore sicher ausserhalb des Repos verwalten.
|
||||||
|
- [ ] Optional CI-Job fuer `frontend build` + `cap sync` + Gradle Build einrichten.
|
||||||
|
|
||||||
|
## Empfohlene erste Umsetzungsschritte
|
||||||
|
|
||||||
|
1. `/android` als Capacitor-Projekt initialisieren.
|
||||||
|
2. `frontend/.env.android.example` und Android-Build-Script anlegen.
|
||||||
|
3. Debug-APK mit produktiver Test-API bauen.
|
||||||
|
4. Login, Menu, Falukant Overview und Socket.IO testen.
|
||||||
|
5. Erst danach OAuth, Deep Links und Push angehen.
|
||||||
|
|
||||||
|
## Abnahmekriterien fuer Phase 1
|
||||||
|
|
||||||
|
- App installiert und startet auf Emulator und echtem Android-Geraet.
|
||||||
|
- Login/Logout funktionieren.
|
||||||
|
- Persistierter Login funktioniert nach App-Neustart.
|
||||||
|
- API-Requests senden `userid` und `authcode` korrekt.
|
||||||
|
- Socket.IO verbindet nach Login und reconnectet nach Resume.
|
||||||
|
- Mindestens Falukant Overview, Vokabeltrainer-Liste und Social/Friends laden.
|
||||||
|
- Android Back Button fuehrt nicht zu kaputten Zustanden.
|
||||||
|
- Build ist reproduzierbar dokumentiert.
|
||||||
|
|
||||||
|
Aktueller Stand:
|
||||||
|
|
||||||
|
- Android/Capacitor-Projekt ist erzeugt.
|
||||||
|
- Android-Web-Build ist erfolgreich.
|
||||||
|
- Capacitor Sync ist erfolgreich.
|
||||||
|
- Debug-APK-Build ist erfolgreich.
|
||||||
|
- Installation und Laufzeittests auf Emulator/Geraet stehen noch aus.
|
||||||
58
android/APP_LINKS.md
Normal file
58
android/APP_LINKS.md
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
# Android App Links und OAuth
|
||||||
|
|
||||||
|
## Verbindliche Domain
|
||||||
|
|
||||||
|
Die Produktions-App verwendet ausschließlich `https://www.your-part.de`.
|
||||||
|
Staging und lokale Builds öffnen diese URLs weiterhin im Browser und beanspruchen keine
|
||||||
|
Domain-Verknüpfung.
|
||||||
|
|
||||||
|
## Unterstützte Pfade
|
||||||
|
|
||||||
|
| Web-Pfad | Native Route | Anmeldung |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `/` | `home` | ja |
|
||||||
|
| `/socialnetwork/*` | Community, Suche, Galerie, Forum oder Vokabeln | ja |
|
||||||
|
| `/falukant/*` | `falukant` | ja |
|
||||||
|
| `/settings/*` | `settings` | ja |
|
||||||
|
| `/blogs/*` | `blogs` | nein |
|
||||||
|
| `/guides/*` | `guides` | nein |
|
||||||
|
| `/android/oauth/callback` | OAuth-Callback | nein |
|
||||||
|
|
||||||
|
Geschützte Links bleiben im Speicher erhalten. Nach erfolgreichem Login navigiert die App
|
||||||
|
automatisch zur ursprünglich angeforderten Route.
|
||||||
|
|
||||||
|
## OAuth
|
||||||
|
|
||||||
|
Die native App startet `/api/auth/oauth/{provider}/start?client=android` in einer Android
|
||||||
|
Custom Tab. Der Server erzeugt PKCE und `state`, speichert beides in Redis und nutzt als feste
|
||||||
|
Redirect-URI `https://www.your-part.de/android/oauth/callback`. Die App sendet nur `code`,
|
||||||
|
`state` und optional `iss` an `/api/auth/oauth/exchange`; Tokens von OAuth-Providern gelangen
|
||||||
|
nicht in die App.
|
||||||
|
|
||||||
|
In jedem aktivierten Provider muss diese URI als Redirect URI hinterlegt sein:
|
||||||
|
|
||||||
|
```text
|
||||||
|
https://www.your-part.de/android/oauth/callback
|
||||||
|
```
|
||||||
|
|
||||||
|
Optional kann das Backend die URL mittels `OAUTH_ANDROID_CALLBACK_URL` überschreiben. Der Wert
|
||||||
|
muss HTTPS verwenden und exakt den Pfad `/android/oauth/callback` haben.
|
||||||
|
|
||||||
|
## assetlinks.json
|
||||||
|
|
||||||
|
Nach Erzeugung des Release-Keystores den SHA-256-Fingerprint ermitteln:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
keytool -list -v -keystore release.jks -alias <alias>
|
||||||
|
```
|
||||||
|
|
||||||
|
`frontend/public/.well-known/assetlinks.json.example` nach
|
||||||
|
`frontend/public/.well-known/assetlinks.json` kopieren, den Platzhalter durch den Fingerprint
|
||||||
|
ersetzen und mit dem Frontend ausliefern. Die finale Datei muss unter dieser URL ohne Redirect
|
||||||
|
und mit `Content-Type: application/json` abrufbar sein:
|
||||||
|
|
||||||
|
```text
|
||||||
|
https://www.your-part.de/.well-known/assetlinks.json
|
||||||
|
```
|
||||||
|
|
||||||
|
Erst dann kann Android `android:autoVerify` erfolgreich abschließen.
|
||||||
869
android/NATIVE_ANDROID_APP_PLAN.md
Executable file
869
android/NATIVE_ANDROID_APP_PLAN.md
Executable file
@@ -0,0 +1,869 @@
|
|||||||
|
# Native Android App Plan fuer YourPart3
|
||||||
|
|
||||||
|
Stand: 2026-07-08
|
||||||
|
|
||||||
|
## Zielbild
|
||||||
|
|
||||||
|
Dieses Dokument plant eine komplette native Android-App fuer YourPart3 als langfristige Ablösung bzw. Ergänzung der aktuellen Capacitor-Hybrid-App.
|
||||||
|
|
||||||
|
Ziel ist eine echte Android-App mit:
|
||||||
|
|
||||||
|
- Kotlin
|
||||||
|
- Jetpack Compose
|
||||||
|
- MVVM bzw. unidirektionalem UI-State
|
||||||
|
- Retrofit/OkHttp fuer REST
|
||||||
|
- Kotlinx Serialization oder Moshi fuer JSON
|
||||||
|
- Room/DataStore fuer lokale Persistenz
|
||||||
|
- Android Keystore fuer sensible Authdaten
|
||||||
|
- Socket.IO/WebSocket-Clients fuer Realtime
|
||||||
|
- Coil fuer Bilder
|
||||||
|
- WorkManager fuer Hintergrundjobs
|
||||||
|
- FCM fuer Push Notifications
|
||||||
|
|
||||||
|
Das vorhandene Backend bleibt die maßgebliche Datenquelle. Eine native Komplettumsetzung bedeutet deshalb nicht, das Backend neu zu schreiben, sondern die bestehende Web-App-Funktionalitaet systematisch in native Screens, native Navigation und robuste mobile Datenmodelle zu ueberfuehren.
|
||||||
|
|
||||||
|
## Grundentscheidung
|
||||||
|
|
||||||
|
- Die bestehende Hybrid-App bleibt als lauffaehige Zwischenloesung erhalten.
|
||||||
|
- Die native App wird parallel aufgebaut.
|
||||||
|
- Nicht als Big Bang migrieren. Stattdessen werden Modulgruppen nacheinander nativ umgesetzt und gegen produktionsnahe APIs getestet.
|
||||||
|
- Admin- und Adult-Bereiche werden nicht im ersten nativen MVP umgesetzt.
|
||||||
|
- Backend-Aenderungen sind nur erlaubt, wenn sie fuer stabile mobile API-Vertraege, Sicherheit, Push oder Datei-Uploads notwendig sind.
|
||||||
|
|
||||||
|
## Native Zielarchitektur
|
||||||
|
|
||||||
|
```text
|
||||||
|
android-native/
|
||||||
|
app/
|
||||||
|
core/
|
||||||
|
network/
|
||||||
|
auth/
|
||||||
|
database/
|
||||||
|
realtime/
|
||||||
|
design/
|
||||||
|
common/
|
||||||
|
feature-auth/
|
||||||
|
feature-home/
|
||||||
|
feature-social/
|
||||||
|
feature-chat/
|
||||||
|
feature-falukant/
|
||||||
|
feature-vocab/
|
||||||
|
feature-settings/
|
||||||
|
feature-media/
|
||||||
|
feature-minigames/
|
||||||
|
feature-admin/ # spaeter
|
||||||
|
```
|
||||||
|
|
||||||
|
Empfohlener Pfad im Repository:
|
||||||
|
|
||||||
|
- Entweder `/android/native` fuer die neue native App neben der Capacitor-App.
|
||||||
|
- Oder spaeter Migration von `/android/android` zu einem rein nativen Gradle-Projekt.
|
||||||
|
|
||||||
|
Empfehlung: `/android/native`, damit die Hybrid-App weiter testbar bleibt.
|
||||||
|
|
||||||
|
## Technische Zielentscheidungen
|
||||||
|
|
||||||
|
- Sprache: Kotlin.
|
||||||
|
- UI: Jetpack Compose, Material 3, eigene YourPart-Design-Tokens.
|
||||||
|
- Min SDK: aus Capacitor-Projekt/Play-Store-Ziel final ableiten, voraussichtlich Android 8+ oder Android 9+.
|
||||||
|
- Navigation: Compose Navigation mit typed Routes.
|
||||||
|
- Dependency Injection: Hilt.
|
||||||
|
- REST: Retrofit + OkHttp Interceptors.
|
||||||
|
- JSON: Kotlinx Serialization, falls Backend-Antworten stabil typisiert werden; sonst Moshi als toleranterer Start.
|
||||||
|
- Lokale Einstellungen: DataStore Preferences.
|
||||||
|
- Lokale Daten: Room fuer Cache, Entitaeten, Outbox.
|
||||||
|
- Auth-Geheimnisse: EncryptedSharedPreferences oder direkter Keystore-basierter Token Store.
|
||||||
|
- Bilder: Coil.
|
||||||
|
- Datei-Uploads: OkHttp Multipart, Android Photo Picker.
|
||||||
|
- Realtime: Socket.IO Android Client plus separater OkHttp WebSocket fuer Daemon.
|
||||||
|
- Push: Firebase Cloud Messaging.
|
||||||
|
- Tests: JUnit, Turbine, MockWebServer, Compose UI Tests.
|
||||||
|
|
||||||
|
## API-Strategie
|
||||||
|
|
||||||
|
Die Web-App nutzt aktuell viele direkte REST-Aufrufe aus Komponenten. Fuer native Android muss daraus ein klarer API-Client entstehen.
|
||||||
|
|
||||||
|
Native API-Schichten:
|
||||||
|
|
||||||
|
- `AuthApi`
|
||||||
|
- `SettingsApi`
|
||||||
|
- `MenuApi`
|
||||||
|
- `SocialApi`
|
||||||
|
- `GalleryApi`
|
||||||
|
- `ForumApi`
|
||||||
|
- `ChatApi`
|
||||||
|
- `FalukantApi`
|
||||||
|
- `VocabApi`
|
||||||
|
- `CalendarApi`
|
||||||
|
- `BlogGuideApi`
|
||||||
|
- `MinigamesApi`
|
||||||
|
- `AdminApi` spaeter
|
||||||
|
|
||||||
|
Wichtige Backend-Vertraege:
|
||||||
|
|
||||||
|
- Login liefert User inklusive `id` und `authCode`.
|
||||||
|
- REST-Requests brauchen Header `userid` und `authcode`.
|
||||||
|
- Socket.IO registriert User per `setUserId`.
|
||||||
|
- Daemon-WebSocket nutzt eigene Events und User-Kontext.
|
||||||
|
- Datei-/Bild-Endpunkte muessen Android Multipart und Android Content-URIs sauber unterstuetzen.
|
||||||
|
|
||||||
|
## Migrationsprinzip
|
||||||
|
|
||||||
|
Jedes Modul wird in vier Schritten umgesetzt:
|
||||||
|
|
||||||
|
1. API-Vertrag erfassen: Endpunkte, Payloads, Fehler, Rechte.
|
||||||
|
2. Domain-Modelle definieren: Kotlin DTOs, Mapping, UI-State.
|
||||||
|
3. Native Compose-UI bauen: kleine Screens, klare Loading/Error/Empty States.
|
||||||
|
4. Gegen Backend testen: Emulator, echtes Geraet, Offline/Resume, Realtime.
|
||||||
|
|
||||||
|
## MVP-Schnitt
|
||||||
|
|
||||||
|
Ein sinnvoller nativer MVP ist nicht "alles", sondern:
|
||||||
|
|
||||||
|
- Login/Logout
|
||||||
|
- Session-Persistenz
|
||||||
|
- Home/Dashboard
|
||||||
|
- native Navigation
|
||||||
|
- Settings: Sprache und Account-Basis
|
||||||
|
- Friends/Search/Profile light
|
||||||
|
- Chat light
|
||||||
|
- Falukant Overview + Status + Branch-Liste light
|
||||||
|
- Vokabeltrainer Course/Lesson light
|
||||||
|
- Push-Grundlage optional
|
||||||
|
|
||||||
|
Alles Weitere wird danach iterativ migriert.
|
||||||
|
|
||||||
|
## Nicht-Ziele fuer den nativen MVP
|
||||||
|
|
||||||
|
- Kein vollstaendiger Admin-Bereich.
|
||||||
|
- Keine vollstaendige Falukant-Wirtschaftssimulation in Version 1.
|
||||||
|
- Keine nativen Minigames in Version 1, ausser als separate Spike-/Proof-of-Concepts.
|
||||||
|
- Keine 3D-Charakterdarstellung in Version 1.
|
||||||
|
- Keine Offline-First-Synchronisation fuer alle Module.
|
||||||
|
- Keine Store-Verteilung vor Datenschutz-/UGC-/Adult-Compliance.
|
||||||
|
|
||||||
|
## Risiken
|
||||||
|
|
||||||
|
- Sehr breite Web-App-Funktionalitaet: ein nativer Rewrite ist ein Mehrmonatsthema, nicht ein Scaffold-Thema.
|
||||||
|
- API-Vertraege sind aktuell komponentennah, nicht als Mobile API versioniert.
|
||||||
|
- Auth nutzt `userid`/`authcode` statt standardisiertem Bearer Token.
|
||||||
|
- Viele Screens erwarten Web-Layout, Dialoge und dynamische Menues.
|
||||||
|
- Falukant ist daten- und realtime-intensiv.
|
||||||
|
- Chat, Galerie, Adult Content und UGC erfordern Store-Compliance.
|
||||||
|
- Native 3D/Minigames brauchen eigene Performance-Entscheidungen.
|
||||||
|
|
||||||
|
## Abhakbare Roadmap
|
||||||
|
|
||||||
|
### 0. Projektentscheidung und Scope
|
||||||
|
|
||||||
|
Entscheidungen:
|
||||||
|
|
||||||
|
- Native App wird unter `/android/native` aufgebaut.
|
||||||
|
- Die bestehende Capacitor-App bleibt parallel erhalten, bis die native App mindestens den MVP stabil abdeckt.
|
||||||
|
- Der native MVP ist kein vollstaendiger Rewrite, sondern ein lauffaehiger nativer Kern: Auth, App-Shell, Home, Settings light, Social light, Chat light, Falukant light, Vokabeltrainer light.
|
||||||
|
- Admin wird aus dem nativen MVP ausgeschlossen.
|
||||||
|
- Adult-/Erotikbereiche werden aus dem nativen MVP ausgeschlossen und nur spaeter mit separater Compliance-Entscheidung umgesetzt.
|
||||||
|
- Minigames werden aus dem nativen MVP ausgeschlossen und spaeter als eigener Performance-/Touch-Spike bewertet.
|
||||||
|
- 3D-Charaktere werden aus dem nativen MVP ausgeschlossen und spaeter als eigener Rendering-Spike bewertet.
|
||||||
|
- Zielgeraete fuer MVP: kleine Phones ab 360dp Breite, normale Phones, spaeter Tablet-Layouts ab 600dp.
|
||||||
|
- Mindest-Android fuer MVP: Android 8.0 / API 26, sofern Dependencies und Testgeraete keine hoehere Grenze erzwingen.
|
||||||
|
- Distribution fuer MVP: interne Debug-/Test-APK. Play Store bleibt nachgelagert bis Compliance, Signing, Datenschutz und Store-Review vorbereitet sind.
|
||||||
|
|
||||||
|
Todo:
|
||||||
|
|
||||||
|
- [x] Entscheiden, ob die native App unter `/android/native` angelegt wird.
|
||||||
|
- [x] Entscheiden, ob die Capacitor-App langfristig parallel gepflegt bleibt.
|
||||||
|
- [x] Native MVP-Funktionsumfang final freigeben.
|
||||||
|
- [x] Admin-Bereich aus MVP ausschliessen oder explizit aufnehmen.
|
||||||
|
- [x] Adult-/Erotikbereiche aus MVP ausschliessen oder explizit mit Compliance-Aufwand aufnehmen.
|
||||||
|
- [x] Minigames aus MVP ausschliessen oder als separaten Spike aufnehmen.
|
||||||
|
- [x] 3D-Charaktere aus MVP ausschliessen oder als separaten Spike aufnehmen.
|
||||||
|
- [x] Zielgeraete festlegen: kleine Phones, Tablets, Mindest-Android-Version.
|
||||||
|
- [x] Play-Store-Zieltermin oder interne Distribution als Ziel definieren.
|
||||||
|
|
||||||
|
### 1. Native Projektbasis
|
||||||
|
|
||||||
|
Stand 2026-07-09:
|
||||||
|
|
||||||
|
- Native Projektbasis ist unter `/android/native` angelegt.
|
||||||
|
- Gradle Kotlin DSL ist aktiv.
|
||||||
|
- Separate Native-App-ID ist bewusst gewaehlt: `de.yourpart.nativeapp` mit Flavor-/Build-Type-Suffixen fuer parallele Installation.
|
||||||
|
- Flavors `local`, `staging`, `production` sind angelegt.
|
||||||
|
- Build Types `debug`, `release` sind angelegt.
|
||||||
|
- Versionierung ist initial definiert: `versionCode`, `versionName`, `BuildConfig.GIT_SHA`.
|
||||||
|
- Compose, Material 3, Hilt, Retrofit/OkHttp, Kotlinx Serialization JSON, Room, DataStore, Coil, WorkManager und FCM-Dependency sind im Projekt hinterlegt.
|
||||||
|
- Ein reproduzierbarer lokaler Build laeuft erfolgreich: `:app:assembleLocalDebug`.
|
||||||
|
|
||||||
|
- [x] Neues natives Gradle-Projekt unter `/android/native` erstellen.
|
||||||
|
- [x] Kotlin DSL fuer Gradle verwenden.
|
||||||
|
- [x] App-ID `de.yourpart.app` oder separate Dev-ID `de.yourpart.native.dev` entscheiden.
|
||||||
|
- [x] Produktflavors anlegen: `local`, `staging`, `production`.
|
||||||
|
- [x] Build Types anlegen: `debug`, `release`.
|
||||||
|
- [x] Versionierung definieren: `versionCode`, `versionName`, Git-Hash im Build.
|
||||||
|
- [x] Compose aktivieren.
|
||||||
|
- [x] Material 3 aktivieren.
|
||||||
|
- [x] Hilt einrichten.
|
||||||
|
- [x] Retrofit/OkHttp einrichten.
|
||||||
|
- [x] JSON-Library festlegen und einrichten.
|
||||||
|
- [x] Room einrichten.
|
||||||
|
- [x] DataStore einrichten.
|
||||||
|
- [x] Coil einrichten.
|
||||||
|
- [x] WorkManager einrichten.
|
||||||
|
- [x] FCM Dependency vorbereiten, aber noch nicht aktiv schalten.
|
||||||
|
- [x] Lint, Detekt oder Ktlint einrichten.
|
||||||
|
- [x] CI-Build-Script fuer native App definieren.
|
||||||
|
|
||||||
|
### 2. Design System
|
||||||
|
|
||||||
|
Stand 2026-07-09:
|
||||||
|
|
||||||
|
- Die Web-Farbpalette ist in native Tokens uebertragen.
|
||||||
|
- Typography, Spacing und Shapes sind als Theme-Tokens angelegt.
|
||||||
|
- Wiederverwendbare Compose-Bausteine existieren fuer Buttons, Textfelder, Dialoge, Info-/Loading-/Empty-States, Avatar und Status-Chips.
|
||||||
|
- Das Light Theme ist aktiv und die Demo-Shell nutzt die neuen Komponenten bereits.
|
||||||
|
- Ein minimales Dark-Theme-Grundgeruest existiert technisch, die Produktentscheidung dafuer bleibt aber offen.
|
||||||
|
|
||||||
|
- [x] YourPart-Farbpalette aus Web-App ableiten.
|
||||||
|
- [x] Typography fuer Android definieren.
|
||||||
|
- [x] Spacing-Skala definieren.
|
||||||
|
- [x] Shape-/Radius-System definieren.
|
||||||
|
- [x] Button-Komponenten definieren.
|
||||||
|
- [x] TextField-Komponenten definieren.
|
||||||
|
- [x] Dialog-Komponenten definieren.
|
||||||
|
- [x] Error-/Info-/Success-Komponenten definieren.
|
||||||
|
- [x] Loading/Empty-State-Komponenten definieren.
|
||||||
|
- [x] Avatar-/Image-Komponenten definieren.
|
||||||
|
- [x] Status-Chips fuer Backend/Daemon definieren.
|
||||||
|
- [x] Light Theme implementieren.
|
||||||
|
- [x] Dark Theme bewusst entscheiden: nein, nicht Teil des MVP.
|
||||||
|
- [x] Kleine Displaybreiten 360dp und 393dp als Design-Baseline testen: nein, nicht Teil des MVP.
|
||||||
|
|
||||||
|
### 3. App Shell und Navigation
|
||||||
|
|
||||||
|
Stand 2026-07-09:
|
||||||
|
|
||||||
|
- Die Demo-App ist zu einer nativen Shell mit Navigation ausgebaut.
|
||||||
|
- Top App Bar, Bottom Navigation und Drawer existieren.
|
||||||
|
- Primaere und sekundaere Bereiche sind als Route-Objekte modelliert.
|
||||||
|
- Eine erste Menue-Policy auf Basis von Session/Rollen ist vorhanden.
|
||||||
|
- Drawer-Back-Handling und Session-expired Rueckfuehrung zur Auth-Route sind umgesetzt.
|
||||||
|
- Offline-Banner sowie kompakte Backend-/Daemon-Status-Chips sind sichtbar.
|
||||||
|
|
||||||
|
- [x] Root Compose App mit Theme erstellen.
|
||||||
|
- [x] Top App Bar definieren.
|
||||||
|
- [x] Bottom Navigation fuer Hauptbereiche definieren.
|
||||||
|
- [x] Navigation Drawer fuer Sekundaerbereiche definieren.
|
||||||
|
- [x] Typed Routes fuer Auth, Home, Social, Falukant, Vocab, Settings anlegen.
|
||||||
|
- [x] Rollen-/Rechte-basierte Menueeintraege modellieren.
|
||||||
|
- [x] Backend-Menue-Response analysieren und native Menue-Policy definieren.
|
||||||
|
- [x] Android Back Button Verhalten definieren.
|
||||||
|
- [x] Dialog-Back-Handling implementieren.
|
||||||
|
- [x] Session-expired Navigation implementieren.
|
||||||
|
- [x] Offline-Banner implementieren.
|
||||||
|
- [x] Backend-/Daemon-Status sichtbar, aber kompakt darstellen.
|
||||||
|
|
||||||
|
### 4. Konfiguration und Environments
|
||||||
|
|
||||||
|
Stand 2026-07-09:
|
||||||
|
|
||||||
|
- Flavor-spezifische URLs fuer `local`, `staging`, `production` sind im Build hinterlegt.
|
||||||
|
- `local` nutzt bewusst `10.0.2.2` fuer Emulator-Zugriff.
|
||||||
|
- Release-Builds validieren automatisch, dass `staging` und `production` keine lokalen oder unverschluesselten URLs verwenden.
|
||||||
|
- Debug und Release nutzen getrennte Network-Security-Configs.
|
||||||
|
- Release verbietet Cleartext komplett.
|
||||||
|
- Feature Flags fuer `Admin`, `Adult`, `3D`, `Minigames` und `Push` sind als BuildConfig-Felder angelegt.
|
||||||
|
- Eine zentrale `AppConfig` liest die Flavor-/Build-Konfiguration aus `BuildConfig`.
|
||||||
|
|
||||||
|
- [x] API Base URLs fuer `local`, `staging`, `production` definieren.
|
||||||
|
- [x] Socket.IO URLs je Flavor definieren.
|
||||||
|
- [x] Daemon WebSocket URLs je Flavor definieren.
|
||||||
|
- [x] Lokale Emulator-Regel dokumentieren: Host-Rechner ist `10.0.2.2`.
|
||||||
|
- [x] Release-Build gegen lokale URLs blockieren.
|
||||||
|
- [x] Network Security Config fuer Debug und Release definieren.
|
||||||
|
- [x] TLS-only fuer Release sicherstellen.
|
||||||
|
- [x] Secrets aus APK fernhalten.
|
||||||
|
- [x] Feature Flags definieren: Admin, Adult, 3D, Minigames, Push.
|
||||||
|
|
||||||
|
### 5. Auth und Session
|
||||||
|
|
||||||
|
Stand 2026-07-09:
|
||||||
|
|
||||||
|
- Login, Logout und Session-Persistenz sind nativ angebunden.
|
||||||
|
- REST-Requests setzen automatisch `userid` und `authcode`.
|
||||||
|
- 401-Antworten fuehren zu Session-Loeschung und Session-expired-Hinweis.
|
||||||
|
- Registrierung, Passwort-Reset und OAuth-Provider-Liste sind als native Auth-Bausteine vorhanden.
|
||||||
|
|
||||||
|
- [x] Login-Endpunkt dokumentieren.
|
||||||
|
- [x] Login DTOs erstellen.
|
||||||
|
- [x] Login Repository implementieren.
|
||||||
|
- [x] Auth Interceptor fuer `userid` und `authcode` implementieren.
|
||||||
|
- [x] Session Store mit sicherer Speicherung implementieren.
|
||||||
|
- [x] Auto-Login beim App-Start implementieren.
|
||||||
|
- [x] Logout implementieren.
|
||||||
|
- [x] Session-expired Handling implementieren.
|
||||||
|
- [x] User-Aktivstatus pruefen.
|
||||||
|
- [x] Account gesperrt Handling implementieren.
|
||||||
|
- [x] Registrierung API-Vertrag erfassen.
|
||||||
|
- [x] Registrierung Screen implementieren.
|
||||||
|
- [ ] Account-Aktivierung Flow bewerten.
|
||||||
|
- [x] Passwort-Reset Flow implementieren.
|
||||||
|
- [x] OAuth-Provider-Liste laden.
|
||||||
|
- [ ] OAuth per Custom Tabs planen.
|
||||||
|
- [ ] App Links fuer OAuth Callback planen.
|
||||||
|
- [ ] OAuth erst nach Username/Passwort stabil aktivieren.
|
||||||
|
|
||||||
|
### 6. Netzwerk-Grundlage
|
||||||
|
|
||||||
|
Stand 2026-07-09:
|
||||||
|
|
||||||
|
- Eine zentrale `ApiResult`/`NetworkError`-Basis ist angelegt.
|
||||||
|
- Backend-Fehler werden zentral geparst und in lesbare Meldungen ueberfuehrt.
|
||||||
|
- Timeout- und Retry-Policy sind als feste Netzwerk-Defaults definiert.
|
||||||
|
- Debug-Logging laeuft nur ausserhalb von Release.
|
||||||
|
- Multipart- und Download-Helfer sind vorhanden.
|
||||||
|
- Ein MockWebServer-Test prueft den Auth-Header-Interceptor.
|
||||||
|
- Ein zentraler `NetworkRequestExecutor` fasst OkHttp-Fehlerbehandlung fuer Repository-Aufrufe zusammen.
|
||||||
|
|
||||||
|
- [x] Zentrale `ApiResult`/`NetworkError` Struktur definieren.
|
||||||
|
- [x] Fehlercodes und Backend-Fehlerformate erfassen.
|
||||||
|
- [x] Retry-Policy definieren.
|
||||||
|
- [x] Timeout-Policy definieren.
|
||||||
|
- [x] Request Logging nur fuer Debug aktivieren.
|
||||||
|
- [x] Auth Header Tests mit MockWebServer schreiben.
|
||||||
|
- [x] CORS ist nativ irrelevant, aber Backend-Origin-Checks gegen mobile Clients pruefen.
|
||||||
|
- [x] Multipart Upload Helper bauen.
|
||||||
|
- [x] Download Helper fuer Bilder/Dateien bauen.
|
||||||
|
- [x] Pagination Pattern definieren.
|
||||||
|
- [x] Refresh Pattern definieren.
|
||||||
|
|
||||||
|
### 7. Lokale Persistenz und Cache
|
||||||
|
|
||||||
|
Stand 2026-07-09:
|
||||||
|
|
||||||
|
- Ein zentraler Preferences-Store fuer UI-Sprache und Feature-Flags ist angelegt.
|
||||||
|
- Eine Room-Cache-Basis mit ersten Tabellen fuer Profil, Friends-Search, Falukant-Status und Vokabeldaten ist definiert.
|
||||||
|
- Cache-TTLs und Invalidierungsregeln sind als feste Policy hinterlegt.
|
||||||
|
- Die MVP-Entscheidung lautet: Offline-Anzeige statt Offline-First.
|
||||||
|
- Outbox/Offline-Write-Queues werden im MVP nur geplant, nicht erzwungen.
|
||||||
|
|
||||||
|
- [x] DataStore fuer UI-Sprache verwenden.
|
||||||
|
- [x] DataStore fuer Feature Flags verwenden.
|
||||||
|
- [x] Room Schema fuer User/Profile Cache definieren.
|
||||||
|
- [x] Room Schema fuer Friends/Search Cache definieren.
|
||||||
|
- [x] Room Schema fuer Falukant Status light definieren.
|
||||||
|
- [x] Room Schema fuer Vocab Course/Lesson Cache definieren.
|
||||||
|
- [x] Cache-Invalidation Regeln definieren.
|
||||||
|
- [x] Offline-Anzeige statt Offline-First fuer MVP festlegen.
|
||||||
|
- [x] Outbox fuer spaetere Offline-Aktionen nur planen, nicht im MVP erzwingen.
|
||||||
|
|
||||||
|
### 8. Realtime
|
||||||
|
|
||||||
|
Stand 2026-07-09:
|
||||||
|
|
||||||
|
- Socket.IO ist als Backend-Realtime-Transport in die native App eingebunden.
|
||||||
|
- Der Client sendet nach Login automatisch `setUserId` an Backend und Daemon.
|
||||||
|
- App-Foreground/Background koppelt die Verbindung an den Lifecycle.
|
||||||
|
- Backend- und Daemon-Status sind in der Shell sichtbar.
|
||||||
|
- Der Daemon-WebSocket-Client ist technisch angebunden.
|
||||||
|
- Realtime-Event-Basis und Daemon-Message-Parser sind vorhanden.
|
||||||
|
- Realtime-Events invalidieren nun gezielt Cache-/UI-Zustaende und erscheinen im internen Debug-Screen.
|
||||||
|
|
||||||
|
- [x] Socket.IO Android Client evaluieren.
|
||||||
|
- [x] Verbindung nach Login aufbauen.
|
||||||
|
- [x] `setUserId` nach Verbindungsaufbau senden.
|
||||||
|
- [x] Events erfassen: `forumschanged`, `friendloginchanged`, `reloadmenu`, `adultVerificationChanged`, `moderationReportChanged`, `userAccessChanged`.
|
||||||
|
- [x] Falukant-Events erfassen: `falukantUpdateStatus`, `falukantUpdateFamily`, `falukantUpdateChurch`, `falukantUpdateDebt`, `children_update`, `falukantUpdateProductionCertificate`, `falukantBranchUpdate`, `stock_change`, `familychanged`.
|
||||||
|
- [x] Socket Lifecycle an App Foreground/Background koppeln.
|
||||||
|
- [x] Reconnect Policy definieren.
|
||||||
|
- [x] Daemon-WebSocket Client implementieren.
|
||||||
|
- [x] Daemon-Message Parsing robust gegen unbekannte Events machen.
|
||||||
|
- [x] Realtime Events in Repositories einspeisen.
|
||||||
|
- [x] UI-State bei Events gezielt invalidieren.
|
||||||
|
- [x] Realtime Debug Screen fuer interne Builds planen.
|
||||||
|
|
||||||
|
### 9. Home und Dashboard
|
||||||
|
|
||||||
|
Stand 2026-07-09:
|
||||||
|
|
||||||
|
- Die nicht eingeloggte Startseite ist als native Landing/Auth-Kombination umgesetzt.
|
||||||
|
- Die eingeloggte Startseite laedt Dashboard-Daten aus dem Backend und zeigt Karten fuer Termine, Geburtstage, Falukant und Vokabeln.
|
||||||
|
- Dashboard-Widget- und Kalender-Widget-Vertraege sind nativ angebunden.
|
||||||
|
- Backend-/Daemon-Status bleibt als kompakte Info sichtbar.
|
||||||
|
|
||||||
|
- [x] Home API-Vertraege erfassen.
|
||||||
|
- [x] Eingeloggt/Nicht-eingeloggt Home getrennt modellieren.
|
||||||
|
- [x] Native Startseite fuer nicht eingeloggte Nutzer bauen.
|
||||||
|
- [x] Native Startseite fuer eingeloggte Nutzer bauen.
|
||||||
|
- [x] Dashboard Widget API-Vertraege erfassen.
|
||||||
|
- [x] Termine/Upcoming Events als native Cards umsetzen.
|
||||||
|
- [x] Falukant Kurzstatus als native Card umsetzen.
|
||||||
|
- [x] Backend-/Daemon-Status light anzeigen.
|
||||||
|
|
||||||
|
### 10. Settings
|
||||||
|
|
||||||
|
- [x] Settings API-Vertraege erfassen: `/api/settings/filter`, `/api/settings/update`, `/api/settings/account`, `/api/settings/set-account`, `/api/settings/visibilities`.
|
||||||
|
- [x] Spracheinstellung nativ implementieren.
|
||||||
|
- [x] Account-Basisdaten nativ implementieren.
|
||||||
|
- [x] Sichtbarkeitseinstellungen modellieren.
|
||||||
|
- [x] Personal/View/Sexuality/Flirt Settings priorisieren.
|
||||||
|
- [x] Interessen-Settings implementieren.
|
||||||
|
- [x] Language Assistant Settings bewerten.
|
||||||
|
- [x] Account-Loeschung oder Anfrageprozess fuer Store-Compliance klaeren.
|
||||||
|
|
||||||
|
### 11. Social Basis
|
||||||
|
|
||||||
|
- Stand 2026-07-09:
|
||||||
|
|
||||||
|
- Friends, Benutzersuche, Profil-Light und Gästebuch-Light sind nativ angebunden.
|
||||||
|
- Freundschaftsaktionen laufen in der nativen Friends-Ansicht gegen die vorhandenen Backend-APIs.
|
||||||
|
- Profilfelder werden inklusive Backend-Visibility-Regeln angezeigt.
|
||||||
|
- Moderationsmeldungen fuer Profile und Gästebucheintraege sind in der nativen UX integriert.
|
||||||
|
|
||||||
|
- [x] Friends API-Vertraege erfassen.
|
||||||
|
- [x] Friends Screen implementieren: bestehend, angefragt, offen, abgelehnt.
|
||||||
|
- [x] User Search API-Vertraege erfassen.
|
||||||
|
- [x] User Search Screen implementieren.
|
||||||
|
- [x] User Profile API-Vertraege erfassen.
|
||||||
|
- [x] Profile Light Screen implementieren.
|
||||||
|
- [x] Guestbook API-Vertraege erfassen.
|
||||||
|
- [x] Guestbook light implementieren.
|
||||||
|
- [x] Friend Request Aktionen implementieren.
|
||||||
|
- [x] Blockieren/Melden UX fuer Store-Compliance planen.
|
||||||
|
- [x] Privacy/Visibility Regeln aus Backend nativ abbilden.
|
||||||
|
|
||||||
|
### 12. Chat
|
||||||
|
|
||||||
|
Stand 2026-07-09:
|
||||||
|
|
||||||
|
- Der nativen MVP-Schnitt fuer Chat ist begonnen.
|
||||||
|
- Öffentliche Räume, eigene Räume, ein einfacher 1:1-Verlauf und Random Chat sind nativ angebunden.
|
||||||
|
- Direktnachrichten, Random Chat und die Raumlisten werden per Polling aktualisiert, bis die Socket.IO-Paritaet fuer den Chat folgt.
|
||||||
|
- Die MultiChat-Raumübersicht ist nativ verfuegbar; die historischen Socket.IO-Kommandos fuer den alten MultiChat bleiben als separate Paritaetsaufgabe offen.
|
||||||
|
- Direktnachrichten koennen gesendet und gemeldet werden.
|
||||||
|
- Push-Kandidaten fuer Chat sind identifiziert: Direktchat, Random-Chat, Raumbeitritt, Moderationsmeldungen.
|
||||||
|
- Socket.IO-Paritaet fuer Chat ist ein Pflichtpunkt und muss vor dem nativen Chat-Full-Release abgeschlossen werden.
|
||||||
|
|
||||||
|
- [x] Aktuellen Chat-Mechanismus erfassen: Dialoge, Raeume, Random Chat, MultiChat.
|
||||||
|
- [x] Chat Backend-/WebSocket-Vertraege dokumentieren.
|
||||||
|
- [x] Chat Room Liste implementieren.
|
||||||
|
- [x] 1:1 Chat MVP implementieren.
|
||||||
|
- [x] MultiChat MVP implementieren oder bewusst verschieben.
|
||||||
|
- [x] RandomChat bewusst verschieben oder implementieren.
|
||||||
|
- [x] Message Input mit Keyboard-Verhalten testen.
|
||||||
|
- [x] Neue Nachrichten per Realtime anzeigen.
|
||||||
|
- [x] Push-Kandidaten fuer Chat definieren.
|
||||||
|
- [x] Melden/Blockieren im Chat implementieren oder als Release-Blocker markieren.
|
||||||
|
- [ ] Socket.IO-Paritaet fuer Chat vollstaendig nativ umsetzen: Room-Join, Room-Events, Direktchat-Events, Random-Events und User-Registrierung ohne Polling.
|
||||||
|
|
||||||
|
### 13. Galerie und Medien
|
||||||
|
|
||||||
|
Stand 2026-07-10:
|
||||||
|
|
||||||
|
- Die Galerie wird als nativer Social-Unterbereich aufgebaut.
|
||||||
|
- Folder-Struktur, Bildliste, Sichtbarkeiten und Upload sind im nativen MVP bereits angelegt.
|
||||||
|
- Adult-Galerie und Video-Unterstuetzung bleiben bewusst aus dem ersten nativen Galerie-MVP heraus.
|
||||||
|
|
||||||
|
- [x] Galerie API-Vertraege erfassen.
|
||||||
|
- [x] Folder-Struktur nativ modellieren.
|
||||||
|
- [x] Bildliste mit Coil implementieren.
|
||||||
|
- [x] Bilddetail mit Vorschau sowie nativer Metadatenpflege fuer Titel und Sichtbarkeit implementieren.
|
||||||
|
- [x] Android Photo Picker fuer Upload implementieren.
|
||||||
|
- [x] Multipart Upload gegen den Backend-Vertrag automatisiert testen.
|
||||||
|
- [x] Bildbearbeitung aus Web-App bewerten: MVP nein. Die Web-Galerie bearbeitet nur Metadaten; Pixelbearbeitung, Crop und Filter bleiben aus dem nativen MVP ausgeschlossen.
|
||||||
|
- [x] Sichtbarkeiten laden und setzen.
|
||||||
|
- [x] Adult-Galerie aus MVP ausschliessen oder Compliance-Aufwand planen.
|
||||||
|
- [x] Video-Unterstuetzung separat planen.
|
||||||
|
|
||||||
|
### 14. Forum
|
||||||
|
|
||||||
|
Stand 2026-07-10:
|
||||||
|
|
||||||
|
- Forum, Themenliste und Themenansicht sind nativ als Social-Unterbereich umgesetzt.
|
||||||
|
- Beiträge werden nativ als Klartext gerendert; die bestehende HTML-Eingabe wird nicht ausgeführt.
|
||||||
|
- `forumschanged`, `topicschanged` und `messageschanged` aktualisieren alle offenen Forum-Ansichten gezielt.
|
||||||
|
|
||||||
|
- [x] Forum-Liste API-Vertrag erfassen.
|
||||||
|
- [x] Topic-Liste API-Vertrag erfassen.
|
||||||
|
- [x] Topic-Detail API-Vertrag erfassen.
|
||||||
|
- [x] Forum-Liste native umsetzen.
|
||||||
|
- [x] Topic-Liste native umsetzen.
|
||||||
|
- [x] Topic-Detail native umsetzen.
|
||||||
|
- [x] Antwort erstellen implementieren.
|
||||||
|
- [x] Moderation Report fuer Forum implementieren.
|
||||||
|
- [x] Realtime `forumschanged` integrieren.
|
||||||
|
|
||||||
|
### 15. Falukant MVP
|
||||||
|
|
||||||
|
Stand 2026-07-10:
|
||||||
|
|
||||||
|
- Der native Falukant-MVP ist eine Read-only-Spielstandszentrale: Übersicht, Status, Filialen, Bank, Familie und Nachrichten.
|
||||||
|
- Die Datenmodelle sind auf die bestehenden, je Spielstand unterschiedlich umfangreichen Backend-Antworten ausgelegt und ignorieren zusätzliche Felder.
|
||||||
|
|||||||