Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f147481606 | ||
|
|
ebb0b63411 | ||
|
|
8248816577 | ||
|
|
db454b0ebc | ||
|
|
74664612fd | ||
|
|
f60b8795dc | ||
|
|
a3ad273b5f | ||
|
|
50f1638805 | ||
|
|
cf8762560e | ||
|
|
f8262dbe7f | ||
|
|
37b44da41f | ||
|
|
9693fefa81 | ||
|
|
9ed9d732f6 | ||
|
|
ef1b37995f | ||
|
|
8e1e1c0eca | ||
|
|
4c0a1fd5ad | ||
|
|
70c26e9fb1 | ||
|
|
40ed13cbba | ||
|
|
2ee64724d0 | ||
|
|
88550940a3 | ||
|
|
20aea17a55 | ||
|
|
4393e3271e | ||
|
|
0487dbdcde | ||
|
|
58e38a0a10 | ||
|
|
e83b367e3f | ||
|
|
b82b486314 | ||
|
|
d292cd00b7 | ||
|
|
86db47c291 | ||
|
|
181807e090 | ||
|
|
fe24f1ea0d | ||
|
|
f4e96e32fd | ||
|
|
f1c4ce06fb | ||
|
|
af483e155b | ||
|
|
b4a2c261b5 | ||
|
|
4df54be0df |
45
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: '[<SOURCE>]'
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
Please add the source type for your bug to the title of the issue, e.g. "[rss] RSS Feed could not be parsed". When
|
||||
your problem is not related to a source use "[core]", e.g. "[core] Feature xyz is not working"
|
||||
-->
|
||||
|
||||
## Describe the Bug
|
||||
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
## Platform
|
||||
|
||||
- [ ] Android
|
||||
- [ ] iOS
|
||||
- [ ] Linux
|
||||
- [ ] macOS
|
||||
- [ ] Windows
|
||||
- [ ] Web
|
||||
|
||||
## To Reproduce
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
## Expected behavior
|
||||
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
## Screenshots
|
||||
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
## Additional context
|
||||
|
||||
Add any other context about the problem here.
|
||||
31
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: '[<SOURCE>]'
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
Please add the source type for your bug to the title of the issue, e.g. "[rss] RSS Feed could not be parsed". When
|
||||
your problem is not related to a source use "core", e.g. "[core] Feature xyz is not working"
|
||||
-->
|
||||
|
||||
## Is your feature request related to a problem? Please describe
|
||||
|
||||
A clear and concise description of what the problem is. Ex. I'm always
|
||||
frustrated when [...]
|
||||
|
||||
## Describe the solution you'd like
|
||||
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
## Describe alternatives you've considered
|
||||
|
||||
A clear and concise description of any alternative solutions or features you've
|
||||
considered.
|
||||
|
||||
## Additional context
|
||||
|
||||
Add any other context or screenshots about the feature request here.
|
||||
11
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<!--
|
||||
Keep PR title verbose enough and add prefix telling about what source it touches e.g "[rss] Add feature xyz" or if the
|
||||
the PR is not realated to a source use "[core]", e.g. "[core] Fix xyz".
|
||||
|
||||
If you add a breaking change within your PR you should add ":warning:" to the title,
|
||||
e.g. ":warning: [core] My breaking change"
|
||||
-->
|
||||
|
||||
<!--
|
||||
Description of what have been changed. Please also reference an issue, when available.
|
||||
-->
|
||||
BIN
.github/assets/badge-app-store.png
vendored
|
Before Width: | Height: | Size: 20 KiB |
47
.github/assets/badge-app-store.svg
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 120 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M110.135,0L9.535,0C9.168,0 8.806,0 8.44,0.002C8.134,0.004 7.83,0.01 7.521,0.015C6.85,0.023 6.18,0.082 5.517,0.191C4.856,0.304 4.215,0.515 3.616,0.818C3.019,1.124 2.472,1.522 1.998,1.997C1.52,2.471 1.122,3.018 0.819,3.618C0.515,4.217 0.305,4.859 0.194,5.521C0.083,6.183 0.023,6.853 0.015,7.523C0.006,7.83 0.005,8.138 0,8.444L0,31.559C0.005,31.869 0.006,32.17 0.015,32.481C0.023,33.151 0.083,33.821 0.194,34.482C0.304,35.145 0.515,35.788 0.819,36.387C1.122,36.985 1.52,37.53 1.998,38.001C2.471,38.478 3.017,38.876 3.616,39.18C4.215,39.484 4.855,39.697 5.517,39.81C6.18,39.919 6.85,39.978 7.521,39.987C7.83,39.994 8.134,39.998 8.44,39.998C8.806,40 9.168,40 9.535,40L110.135,40C110.494,40 110.859,40 111.219,39.998C111.523,39.998 111.836,39.994 112.141,39.987C112.811,39.979 113.479,39.92 114.141,39.81C114.804,39.696 115.448,39.483 116.049,39.18C116.647,38.876 117.194,38.478 117.666,38.001C118.142,37.528 118.541,36.983 118.848,36.387C119.15,35.787 119.358,35.145 119.467,34.482C119.578,33.821 119.64,33.151 119.652,32.481C119.656,32.17 119.656,31.869 119.656,31.559C119.664,31.195 119.664,30.834 119.664,30.465L119.664,9.536C119.664,9.17 119.664,8.807 119.656,8.444C119.656,8.138 119.656,7.83 119.652,7.523C119.64,6.852 119.578,6.183 119.467,5.521C119.358,4.859 119.149,4.217 118.848,3.618C118.23,2.415 117.251,1.436 116.049,0.818C115.448,0.516 114.804,0.304 114.141,0.191C113.48,0.081 112.811,0.022 112.141,0.015C111.836,0.01 111.523,0.004 111.219,0.002C110.859,-0 110.494,-0 110.135,-0L110.135,0Z" style="fill:rgb(166,166,166);fill-rule:nonzero;"/>
|
||||
<path d="M8.445,39.125C8.14,39.125 7.843,39.121 7.541,39.114C6.914,39.106 6.29,39.052 5.671,38.951C5.095,38.852 4.537,38.667 4.015,38.403C3.498,38.142 3.026,37.798 2.618,37.387C2.204,36.98 1.859,36.508 1.597,35.99C1.333,35.469 1.149,34.91 1.054,34.333C0.951,33.713 0.896,33.086 0.888,32.458C0.881,32.247 0.873,31.545 0.873,31.545L0.873,8.444C0.873,8.444 0.882,7.753 0.888,7.55C0.895,6.922 0.951,6.297 1.053,5.678C1.149,5.099 1.332,4.539 1.597,4.016C1.857,3.498 2.2,3.026 2.612,2.618C3.023,2.206 3.496,1.861 4.014,1.595C4.535,1.332 5.092,1.149 5.667,1.051C6.288,0.95 6.915,0.895 7.543,0.887L8.445,0.875L111.214,0.875L112.127,0.888C112.75,0.895 113.371,0.949 113.985,1.05C114.566,1.149 115.13,1.334 115.656,1.598C116.694,2.133 117.539,2.979 118.071,4.018C118.332,4.538 118.512,5.094 118.606,5.667C118.71,6.291 118.768,6.922 118.78,7.554C118.783,7.837 118.783,8.142 118.783,8.444C118.791,8.819 118.791,9.176 118.791,9.536L118.791,30.465C118.791,30.828 118.791,31.183 118.783,31.54C118.783,31.865 118.783,32.163 118.779,32.47C118.768,33.091 118.71,33.71 118.608,34.323C118.515,34.904 118.333,35.468 118.068,35.993C117.805,36.506 117.462,36.973 117.053,37.379C116.644,37.793 116.172,38.138 115.653,38.401C115.128,38.667 114.566,38.853 113.985,38.951C113.367,39.052 112.742,39.107 112.116,39.114C111.823,39.121 111.517,39.125 111.219,39.125L110.135,39.127L8.445,39.125Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g id="_Group_">
|
||||
<g id="_Group_2_" serif:id="_Group_2">
|
||||
<g id="_Group_3_" serif:id="_Group_3">
|
||||
<path id="_Path_" d="M24.769,20.301C24.791,18.606 25.682,17.036 27.125,16.149C26.21,14.842 24.729,14.041 23.134,13.991C21.455,13.815 19.827,14.996 18.971,14.996C18.099,14.996 16.782,14.008 15.363,14.038C13.498,14.098 11.797,15.135 10.89,16.766C8.956,20.114 10.399,25.035 12.251,27.742C13.178,29.067 14.261,30.547 15.679,30.495C17.066,30.437 17.584,29.61 19.258,29.61C20.917,29.61 21.403,30.495 22.849,30.462C24.338,30.437 25.275,29.13 26.17,27.792C26.836,26.848 27.348,25.804 27.688,24.7C25.924,23.954 24.771,22.216 24.769,20.301Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path id="_Path_2_" serif:id="_Path_2" d="M22.037,12.211C22.848,11.237 23.249,9.984 23.152,8.72C21.912,8.85 20.766,9.443 19.944,10.38C19.132,11.304 18.721,12.514 18.8,13.741C20.056,13.754 21.25,13.189 22.037,12.211Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M42.302,27.14L37.569,27.14L36.432,30.496L34.427,30.496L38.911,18.078L40.994,18.078L45.477,30.496L43.438,30.496L42.302,27.14ZM38.059,25.591L41.811,25.591L39.961,20.144L39.91,20.144L38.059,25.591Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M55.16,25.97C55.16,28.783 53.654,30.591 51.381,30.591C50.209,30.652 49.099,30.035 48.533,29.007L48.49,29.007L48.49,33.491L46.631,33.491L46.631,21.442L48.43,21.442L48.43,22.948L48.464,22.948C49.056,21.926 50.166,21.31 51.347,21.348C53.645,21.348 55.16,23.164 55.16,25.97ZM53.25,25.97C53.25,24.137 52.302,22.932 50.857,22.932C49.437,22.932 48.482,24.162 48.482,25.97C48.482,27.794 49.437,29.016 50.857,29.016C52.302,29.016 53.25,27.819 53.25,25.97Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M65.125,25.97C65.125,28.783 63.619,30.591 61.346,30.591C60.174,30.652 59.064,30.035 58.498,29.007L58.455,29.007L58.455,33.491L56.596,33.491L56.596,21.442L58.395,21.442L58.395,22.948L58.429,22.948C59.021,21.926 60.131,21.31 61.312,21.348C63.61,21.348 65.125,23.164 65.125,25.97ZM63.214,25.97C63.214,24.137 62.267,22.932 60.822,22.932C59.402,22.932 58.447,24.162 58.447,25.97C58.447,27.794 59.402,29.016 60.822,29.016C62.267,29.016 63.214,27.819 63.214,25.97L63.214,25.97Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M71.71,27.036C71.848,28.268 73.044,29.076 74.679,29.076C76.246,29.076 77.373,28.268 77.373,27.157C77.373,26.193 76.693,25.616 75.084,25.221L73.474,24.833C71.194,24.282 70.135,23.216 70.135,21.485C70.135,19.343 72.002,17.871 74.654,17.871C77.278,17.871 79.077,19.343 79.137,21.485L77.261,21.485C77.149,20.246 76.125,19.498 74.627,19.498C73.13,19.498 72.106,20.255 72.106,21.356C72.106,22.234 72.76,22.751 74.361,23.146L75.729,23.482C78.277,24.085 79.335,25.108 79.335,26.925C79.335,29.248 77.485,30.703 74.542,30.703C71.788,30.703 69.928,29.282 69.808,27.036L71.71,27.036Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M83.346,19.3L83.346,21.442L85.068,21.442L85.068,22.914L83.346,22.914L83.346,27.905C83.346,28.681 83.691,29.042 84.448,29.042C84.652,29.038 84.856,29.024 85.059,28.999L85.059,30.462C84.719,30.525 84.373,30.554 84.027,30.548C82.194,30.548 81.479,29.859 81.479,28.103L81.479,22.914L80.163,22.914L80.163,21.442L81.479,21.442L81.479,19.3L83.346,19.3Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M86.065,25.97C86.065,23.121 87.743,21.331 90.359,21.331C92.984,21.331 94.654,23.121 94.654,25.97C94.654,28.826 92.993,30.608 90.359,30.608C87.726,30.608 86.065,28.826 86.065,25.97ZM92.76,25.97C92.76,24.016 91.865,22.862 90.359,22.862C88.853,22.862 87.959,24.024 87.959,25.97C87.959,27.932 88.853,29.076 90.359,29.076C91.865,29.076 92.76,27.932 92.76,25.97L92.76,25.97Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M96.186,21.442L97.959,21.442L97.959,22.983L98.002,22.983C98.248,21.995 99.161,21.309 100.179,21.348C100.393,21.347 100.607,21.37 100.816,21.417L100.816,23.155C100.546,23.073 100.264,23.035 99.981,23.043C99.956,23.042 99.93,23.041 99.905,23.041C98.878,23.041 98.032,23.887 98.032,24.914C98.032,24.985 98.036,25.056 98.044,25.126L98.044,30.496L96.186,30.496L96.186,21.442Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M109.384,27.837C109.134,29.48 107.534,30.608 105.486,30.608C102.852,30.608 101.217,28.844 101.217,26.013C101.217,23.173 102.861,21.331 105.408,21.331C107.913,21.331 109.488,23.052 109.488,25.797L109.488,26.434L103.093,26.434L103.093,26.546C103.087,26.615 103.084,26.684 103.084,26.754C103.084,28.047 104.149,29.112 105.442,29.112C105.471,29.112 105.5,29.111 105.529,29.11C106.428,29.195 107.282,28.675 107.62,27.837L109.384,27.837ZM103.102,25.135L107.628,25.135C107.631,25.094 107.632,25.054 107.632,25.014C107.632,23.819 106.649,22.836 105.455,22.836C105.439,22.836 105.423,22.837 105.408,22.837C105.403,22.837 105.399,22.837 105.394,22.837C104.137,22.837 103.102,23.872 103.102,25.129C103.102,25.131 103.102,25.133 103.102,25.135L103.102,25.135Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="_Group_4_" serif:id="_Group_4">
|
||||
<g>
|
||||
<path d="M37.826,8.731C37.889,8.726 37.952,8.724 38.015,8.724C39.463,8.724 40.655,9.916 40.655,11.364C40.655,11.475 40.648,11.586 40.634,11.696C40.634,13.602 39.604,14.698 37.826,14.698L35.671,14.698L35.671,8.731L37.826,8.731ZM36.598,13.854L37.723,13.854C37.76,13.856 37.797,13.857 37.835,13.857C38.864,13.857 39.71,13.011 39.71,11.981C39.71,11.89 39.704,11.799 39.69,11.708C39.702,11.623 39.708,11.538 39.708,11.452C39.708,10.42 38.859,9.571 37.827,9.571C37.792,9.571 37.757,9.572 37.723,9.574L36.598,9.574L36.598,13.854Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M41.681,12.444C41.674,12.377 41.671,12.309 41.671,12.241C41.671,11.071 42.634,10.108 43.804,10.108C44.974,10.108 45.937,11.071 45.937,12.241C45.937,12.309 45.934,12.377 45.928,12.444C45.934,12.513 45.938,12.582 45.938,12.651C45.938,13.822 44.975,14.785 43.804,14.785C42.634,14.785 41.671,13.822 41.671,12.651C41.671,12.582 41.674,12.513 41.681,12.444ZM45.014,12.444C45.014,11.468 44.575,10.897 43.806,10.897C43.033,10.897 42.599,11.468 42.599,12.444C42.599,13.428 43.033,13.995 43.806,13.995C44.575,13.995 45.014,13.424 45.014,12.444L45.014,12.444Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M51.573,14.698L50.651,14.698L49.721,11.381L49.65,11.381L48.724,14.698L47.811,14.698L46.569,10.195L47.471,10.195L48.277,13.631L48.344,13.631L49.27,10.195L50.122,10.195L51.048,13.631L51.118,13.631L51.921,10.195L52.81,10.195L51.573,14.698Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M53.854,10.195L54.709,10.195L54.709,10.91L54.775,10.91C55.006,10.385 55.547,10.061 56.119,10.108C56.156,10.105 56.192,10.104 56.229,10.104C57.032,10.104 57.694,10.765 57.694,11.568C57.694,11.64 57.688,11.712 57.678,11.783L57.678,14.698L56.789,14.698L56.789,12.006C56.789,11.282 56.475,10.922 55.817,10.922C55.801,10.922 55.785,10.921 55.769,10.921C55.203,10.921 54.736,11.388 54.736,11.954C54.736,11.991 54.738,12.027 54.742,12.063L54.742,14.698L53.854,14.698L53.854,10.195Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<rect x="59.094" y="8.437" width="0.889" height="6.261" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M61.218,12.444C61.211,12.377 61.208,12.309 61.208,12.241C61.208,11.071 62.171,10.108 63.342,10.108C64.512,10.108 65.475,11.071 65.475,12.241C65.475,12.309 65.472,12.377 65.465,12.444C65.472,12.513 65.475,12.582 65.475,12.651C65.475,13.821 64.512,14.785 63.342,14.785C62.171,14.785 61.208,13.821 61.208,12.651C61.208,12.582 61.211,12.513 61.218,12.444ZM64.551,12.444C64.551,11.468 64.112,10.897 63.343,10.897C62.57,10.897 62.136,11.468 62.136,12.444C62.136,13.428 62.57,13.995 63.343,13.995C64.112,13.995 64.551,13.424 64.551,12.444L64.551,12.444Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M66.401,13.424C66.401,12.614 67.004,12.146 68.076,12.08L69.295,12.01L69.295,11.621C69.295,11.146 68.981,10.877 68.374,10.877C67.877,10.877 67.534,11.059 67.435,11.377L66.575,11.377C66.666,10.604 67.393,10.108 68.415,10.108C69.543,10.108 70.18,10.67 70.18,11.621L70.18,14.698L69.325,14.698L69.325,14.065L69.254,14.065C68.964,14.526 68.446,14.797 67.902,14.772C67.855,14.777 67.808,14.779 67.761,14.779C67.017,14.779 66.404,14.169 66.401,13.424ZM69.295,13.04L69.295,12.663L68.196,12.733C67.576,12.775 67.294,12.986 67.294,13.383C67.294,13.788 67.646,14.024 68.129,14.024C68.165,14.028 68.201,14.029 68.236,14.029C68.792,14.029 69.258,13.594 69.295,13.04Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M71.348,12.444C71.348,11.021 72.08,10.12 73.217,10.12C73.791,10.094 74.33,10.402 74.598,10.91L74.665,10.91L74.665,8.437L75.553,8.437L75.553,14.698L74.702,14.698L74.702,13.986L74.631,13.986C74.343,14.49 73.797,14.793 73.217,14.772C72.072,14.772 71.348,13.871 71.348,12.444ZM72.266,12.444C72.266,13.399 72.716,13.974 73.469,13.974C74.218,13.974 74.681,13.391 74.681,12.448C74.681,11.51 74.213,10.918 73.469,10.918C72.721,10.918 72.266,11.497 72.266,12.444L72.266,12.444Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M79.23,12.444C79.224,12.377 79.22,12.309 79.22,12.241C79.22,11.071 80.183,10.108 81.354,10.108C82.524,10.108 83.487,11.071 83.487,12.241C83.487,12.309 83.484,12.377 83.477,12.444C83.484,12.513 83.487,12.582 83.487,12.651C83.487,13.822 82.524,14.785 81.354,14.785C80.183,14.785 79.22,13.822 79.22,12.651C79.22,12.582 79.223,12.513 79.23,12.444ZM82.563,12.444C82.563,11.468 82.125,10.897 81.355,10.897C80.583,10.897 80.148,11.468 80.148,12.444C80.148,13.428 80.583,13.995 81.355,13.995C82.125,13.995 82.563,13.424 82.563,12.444Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M84.669,10.195L85.525,10.195L85.525,10.91L85.591,10.91C85.822,10.385 86.363,10.061 86.935,10.108C86.972,10.105 87.008,10.104 87.045,10.104C87.848,10.104 88.509,10.765 88.509,11.568C88.509,11.64 88.504,11.712 88.494,11.783L88.494,14.698L87.605,14.698L87.605,12.006C87.605,11.282 87.291,10.922 86.633,10.922C86.617,10.922 86.601,10.921 86.585,10.921C86.019,10.921 85.552,11.388 85.552,11.954C85.552,11.991 85.554,12.027 85.558,12.063L85.558,14.698L84.669,14.698L84.669,10.195Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M93.515,9.074L93.515,10.215L94.491,10.215L94.491,10.964L93.515,10.964L93.515,13.279C93.515,13.751 93.709,13.958 94.152,13.958C94.265,13.957 94.378,13.95 94.491,13.937L94.491,14.677C94.331,14.706 94.169,14.721 94.007,14.723C93.019,14.723 92.626,14.375 92.626,13.507L92.626,10.964L91.911,10.964L91.911,10.215L92.626,10.215L92.626,9.074L93.515,9.074Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M95.705,8.437L96.585,8.437L96.585,10.918L96.656,10.918C96.897,10.388 97.448,10.065 98.029,10.112C98.056,10.11 98.082,10.11 98.109,10.11C98.923,10.11 99.593,10.779 99.593,11.593C99.593,11.659 99.588,11.725 99.58,11.791L99.58,14.698L98.69,14.698L98.69,12.01C98.69,11.291 98.355,10.926 97.727,10.926C97.699,10.924 97.67,10.923 97.641,10.923C97.064,10.923 96.589,11.398 96.589,11.975C96.589,12.006 96.591,12.037 96.593,12.068L96.593,14.698L95.705,14.698L95.705,8.437Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M104.761,13.482C104.513,14.328 103.687,14.88 102.81,14.785C102.792,14.785 102.774,14.785 102.756,14.785C101.634,14.785 100.711,13.862 100.711,12.74C100.711,12.647 100.717,12.553 100.73,12.46C100.718,12.369 100.712,12.277 100.712,12.185C100.712,11.045 101.649,10.108 102.788,10.108C102.794,10.108 102.8,10.108 102.806,10.108C104.059,10.108 104.815,10.964 104.815,12.378L104.815,12.688L101.635,12.688L101.635,12.738C101.632,12.771 101.631,12.804 101.631,12.838C101.631,13.491 102.168,14.028 102.821,14.028C102.826,14.028 102.83,14.028 102.834,14.028C103.268,14.08 103.693,13.864 103.906,13.482L104.761,13.482ZM101.635,12.031L103.91,12.031C103.912,12.004 103.913,11.977 103.913,11.95C103.913,11.354 103.422,10.864 102.826,10.864C102.818,10.864 102.81,10.864 102.801,10.864C102.796,10.864 102.792,10.864 102.787,10.864C102.155,10.864 101.635,11.384 101.635,12.016C101.635,12.021 101.635,12.026 101.635,12.031L101.635,12.031Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 16 KiB |
BIN
.github/assets/badge-desktop.png
vendored
|
Before Width: | Height: | Size: 19 KiB |
27
.github/assets/badge-flathub.svg
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 300 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;">
|
||||
<g transform="matrix(1,0,0,1,-348.1,-151.685)">
|
||||
<path d="M646.159,168.627C646.159,159.796 638.99,152.627 630.159,152.627L365.042,152.627C356.211,152.627 349.042,159.796 349.042,168.627L349.042,234.41C349.042,243.241 356.211,250.41 365.042,250.41L630.159,250.41C638.99,250.41 646.159,243.241 646.159,234.41L646.159,168.627Z" style="stroke:rgb(136,138,133);stroke-width:1.88px;"/>
|
||||
<g>
|
||||
<path d="M464.084,188.646C467.784,188.646 469.925,186.351 469.925,182.556C469.925,178.778 467.785,176.501 464.209,176.501L460.153,176.501L460.153,188.646L464.084,188.646ZM461.985,187.045L461.985,178.102L464.096,178.102C466.753,178.102 468.123,179.692 468.123,182.556C468.123,185.432 466.753,187.045 463.983,187.045L461.985,187.045ZM478.644,188.83C481.212,188.83 482.89,186.95 482.89,184.133C482.89,181.299 481.212,179.419 478.644,179.419C476.077,179.419 474.398,181.299 474.398,184.133C474.398,186.95 476.077,188.83 478.644,188.83ZM478.65,187.341C476.972,187.341 476.19,185.877 476.19,184.127C476.19,182.384 476.972,180.901 478.65,180.901C480.317,180.901 481.1,182.384 481.1,184.127C481.1,185.877 480.317,187.341 478.65,187.341ZM489.308,188.646L491.111,188.646L492.961,182.07L493.097,182.07L494.947,188.646L496.757,188.646L499.431,179.537L497.598,179.537L495.825,186.197L495.736,186.197L493.957,179.537L492.125,179.537L490.334,186.227L490.245,186.227L488.46,179.537L486.628,179.537L489.308,188.646ZM505.63,183.238C505.63,181.785 506.519,180.955 507.752,180.955C508.956,180.955 509.685,181.743 509.685,183.065L509.685,188.645L511.458,188.645L511.458,182.852C511.458,180.599 510.219,179.419 508.358,179.419C506.988,179.419 506.092,180.053 505.671,181.019L505.558,181.019L505.558,179.537L503.856,179.537L503.856,188.646L505.629,188.646L505.63,183.238ZM518.35,176.501L516.578,176.501L516.578,188.646L518.351,188.646L518.35,176.501ZM527.319,188.83C529.887,188.83 531.565,186.95 531.565,184.133C531.565,181.299 529.887,179.419 527.319,179.419C524.751,179.419 523.073,181.299 523.073,184.133C523.073,186.95 524.751,188.83 527.319,188.83ZM527.325,187.341C525.647,187.341 524.864,185.877 524.864,184.127C524.864,182.384 525.647,180.901 527.324,180.901C528.991,180.901 529.774,182.384 529.774,184.127C529.774,185.877 528.991,187.341 527.324,187.341L527.325,187.341ZM538.937,188.848C540.444,188.848 541.292,188.083 541.63,187.401L541.7,187.401L541.7,188.646L543.432,188.646L543.432,182.597C543.432,179.947 541.345,179.419 539.898,179.419C538.25,179.419 536.732,180.083 536.138,181.743L537.805,182.123C538.065,181.477 538.73,180.853 539.922,180.853C541.066,180.853 541.653,181.453 541.653,182.485L541.653,182.526C541.653,183.173 540.989,183.161 539.353,183.35C537.627,183.552 535.86,184.003 535.86,186.072C535.86,187.863 537.206,188.848 538.938,188.848L538.937,188.848ZM539.323,187.424C538.321,187.424 537.597,186.974 537.597,186.096C537.597,185.147 538.439,184.809 539.465,184.673C540.04,184.596 541.405,184.442 541.659,184.187L541.659,185.361C541.659,186.44 540.799,187.424 539.323,187.424ZM551.95,188.824C553.61,188.824 554.262,187.81 554.583,187.229L554.731,187.229L554.731,188.646L556.462,188.646L556.462,176.5L554.689,176.5L554.689,181.013L554.583,181.013C554.263,180.45 553.658,179.418 551.962,179.418C549.762,179.418 548.142,181.155 548.142,184.108C548.142,187.056 549.738,188.823 551.95,188.823L551.95,188.824ZM552.341,187.312C550.758,187.312 549.933,185.918 549.933,184.092C549.933,182.283 550.74,180.925 552.341,180.925C553.889,180.925 554.719,182.188 554.719,184.092C554.719,186.007 553.871,187.312 552.341,187.312ZM572.744,188.83C575.312,188.83 576.99,186.95 576.99,184.133C576.99,181.299 575.312,179.419 572.744,179.419C570.176,179.419 568.498,181.299 568.498,184.133C568.498,186.95 570.176,188.83 572.744,188.83ZM572.75,187.341C571.072,187.341 570.289,185.877 570.289,184.127C570.289,182.384 571.072,180.901 572.749,180.901C574.416,180.901 575.199,182.384 575.199,184.127C575.199,185.877 574.416,187.341 572.749,187.341L572.75,187.341ZM583.485,183.238C583.485,181.785 584.375,180.955 585.608,180.955C586.812,180.955 587.541,181.743 587.541,183.065L587.541,188.645L589.314,188.645L589.314,182.852C589.314,180.599 588.074,179.419 586.213,179.419C584.843,179.419 583.947,180.053 583.526,181.019L583.414,181.019L583.414,179.537L581.712,179.537L581.712,188.646L583.485,188.646L583.485,183.238Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M460.153,222.645L464.983,222.645L464.983,211.32L476.06,211.32L476.06,207.272L464.982,207.272L464.982,200.034L477.232,200.034L477.232,195.986L460.152,195.986L460.153,222.645Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<rect x="481.41" y="195.986" width="4.712" height="26.66" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M496.718,223.049C499.855,223.049 501.73,221.578 502.588,219.899L502.745,219.899L502.745,222.645L507.275,222.645L507.275,209.263C507.275,203.978 502.966,202.39 499.152,202.39C494.948,202.39 491.719,204.265 490.678,207.91L495.078,208.535C495.546,207.168 496.874,205.996 499.178,205.996C501.365,205.996 502.563,207.116 502.563,209.081L502.563,209.159C502.563,210.513 501.143,210.579 497.616,210.956C493.737,211.372 490.027,212.531 490.027,217.035C490.027,220.965 492.904,223.049 496.718,223.049ZM497.942,219.586C495.976,219.586 494.57,218.688 494.57,216.956C494.57,215.147 496.145,214.392 498.254,214.093C499.491,213.923 501.964,213.611 502.576,213.117L502.576,215.473C502.576,217.699 500.779,219.586 497.942,219.586Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M522.01,202.65L518.066,202.65L518.066,197.86L513.354,197.86L513.354,202.65L510.516,202.65L510.516,206.296L513.354,206.296L513.354,217.412C513.328,221.174 516.062,223.022 519.602,222.918C520.943,222.879 521.867,222.619 522.375,222.45L521.581,218.766C521.321,218.831 520.787,218.948 520.201,218.948C519.016,218.948 518.066,218.532 518.066,216.631L518.066,206.296L522.01,206.296L522.01,202.65Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M531.083,210.93C531.083,208.04 532.88,206.374 535.405,206.374C537.878,206.374 539.336,207.949 539.336,210.644L539.336,222.645L544.049,222.645L544.049,209.915C544.049,205.085 541.315,202.39 537.162,202.39C534.09,202.39 532.138,203.783 531.214,206.048L530.979,206.048L530.979,195.986L526.371,195.986L526.371,222.646L531.083,222.646L531.083,210.93Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M561.583,214.236C561.583,217.282 559.409,218.792 557.326,218.792C555.061,218.792 553.551,217.191 553.551,214.652L553.551,202.651L548.839,202.651L548.839,215.381C548.839,220.185 551.572,222.905 555.504,222.905C558.498,222.905 560.606,221.33 561.518,219.091L561.726,219.091L561.726,222.645L566.295,222.645L566.295,202.651L561.583,202.651L561.583,214.236Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M571.346,222.645L575.98,222.645L575.98,219.495L576.253,219.495C576.995,220.953 578.544,222.997 581.981,222.997C586.693,222.997 590.221,219.261 590.221,212.674C590.221,206.009 586.589,202.39 581.968,202.39C578.44,202.39 576.969,204.512 576.253,205.957L576.058,205.957L576.058,195.986L571.346,195.986L571.346,222.645ZM575.966,212.648C575.966,208.768 577.633,206.256 580.666,206.256C583.803,206.256 585.417,208.925 585.417,212.648C585.417,216.397 583.777,219.13 580.666,219.13C577.659,219.13 575.966,216.527 575.966,212.648Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(1.24662,0,0,1.24662,192.661,67.896)">
|
||||
<circle cx="166.688" cy="95.647" r="9.048" style="fill:white;"/>
|
||||
<path d="M174.826,111.309C174.826,109.371 173.253,107.798 171.315,107.798L161.925,107.798C159.987,107.798 158.414,109.371 158.414,111.309L158.414,120.699C158.414,122.637 159.987,124.21 161.925,124.21L171.315,124.21C173.253,124.21 174.826,122.637 174.826,120.699L174.826,111.309Z" style="fill:white;"/>
|
||||
<g transform="matrix(0.925902,0.53457,0.53457,-0.925902,99.8266,110.693)">
|
||||
<path d="M69.514,58.833L57.486,58.833C56.614,58.833 55.805,58.366 55.369,57.611C54.933,56.856 54.933,55.922 55.369,55.167L56.259,53.625L61.383,44.75C61.819,43.994 62.628,43.527 63.5,43.527C64.372,43.527 65.181,43.994 65.617,44.75L66.507,46.292L71.631,55.167C72.067,55.922 72.067,56.856 71.631,57.611C71.195,58.366 70.386,58.833 69.514,58.833Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<path d="M194.992,116.11C194.992,116.99 194.284,117.697 193.404,117.697L180.704,117.697C179.824,117.697 179.117,116.989 179.117,116.11C179.117,115.23 179.825,114.522 180.704,114.522L193.404,114.522C194.284,114.522 194.992,115.23 194.992,116.11ZM187.054,108.172C187.934,108.172 188.642,108.88 188.642,109.76L188.642,122.46C188.642,123.34 187.934,124.047 187.054,124.047C186.174,124.047 185.467,123.339 185.467,122.46L185.467,109.76C185.467,108.88 186.175,108.172 187.054,108.172Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 9.1 KiB |
BIN
.github/assets/badge-google-play.png
vendored
|
Before Width: | Height: | Size: 16 KiB |
25
.github/assets/badge-google-play.svg
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 563 167" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-miterlimit:2;">
|
||||
<g transform="matrix(4.16667,0,0,4.16667,0,-4)">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M130,41L4.999,41C2.249,41 0,38.75 0,36L0,6C0,3.25 2.249,1 4.999,1L130,1C132.75,1 135,3.25 135,6L135,36C135,38.75 132.75,41 130,41Z" style="fill:rgb(3,4,4);fill-rule:nonzero;"/>
|
||||
<path d="M130,1L4.999,1C2.249,1 0,3.25 0,6L0,36C0,38.75 2.249,41 4.999,41L130,41C132.75,41 135,38.75 135,36L135,6C135,3.25 132.75,1 130,1ZM130,1.8C132.316,1.8 134.2,3.685 134.2,6L134.2,36C134.2,38.316 132.316,40.201 130,40.201L4.999,40.201C2.684,40.201 0.8,38.316 0.8,36L0.8,6C0.8,3.685 2.684,1.8 4.999,1.8L130,1.8Z" style="fill:rgb(167,165,166);fill-rule:nonzero;"/>
|
||||
<path d="M47.376,10.791L44.468,10.791L44.468,11.512L46.647,11.512C46.588,12.098 46.353,12.559 45.96,12.894C45.566,13.229 45.063,13.397 44.468,13.397C43.814,13.397 43.261,13.171 42.809,12.718C42.365,12.257 42.138,11.688 42.138,11C42.138,10.313 42.365,9.743 42.809,9.282C43.261,8.83 43.814,8.604 44.468,8.604C44.803,8.604 45.122,8.662 45.415,8.788C45.708,8.914 45.943,9.09 46.127,9.316L46.68,8.763C46.429,8.478 46.11,8.26 45.717,8.101C45.323,7.942 44.912,7.866 44.468,7.866C43.596,7.866 42.859,8.168 42.256,8.771C41.652,9.375 41.351,10.12 41.351,11C41.351,11.88 41.652,12.626 42.256,13.229C42.859,13.833 43.596,14.134 44.468,14.134C45.381,14.134 46.11,13.841 46.672,13.246C47.166,12.752 47.418,12.081 47.418,11.243C47.418,11.101 47.401,10.95 47.376,10.791Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M48.524,8L48.524,14L52.027,14L52.027,13.263L49.295,13.263L49.295,11.361L51.758,11.361L51.758,10.64L49.295,10.64L49.295,8.738L52.027,8.738L52.027,8L48.524,8Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M56.953,8.738L56.953,8L52.83,8L52.83,8.738L54.506,8.738L54.506,14L55.277,14L55.277,8.738L56.953,8.738Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<rect x="59.937" y="8" width="0.771" height="6" style="fill:white;"/>
|
||||
<path d="M65.803,8.738L65.803,8L61.68,8L61.68,8.738L63.356,8.738L63.356,14L64.127,14L64.127,8.738L65.803,8.738Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M73.605,8.78C73.01,8.168 72.281,7.866 71.409,7.866C70.538,7.866 69.808,8.168 69.213,8.771C68.618,9.366 68.325,10.112 68.325,11C68.325,11.889 68.618,12.634 69.213,13.229C69.808,13.833 70.538,14.134 71.409,14.134C72.272,14.134 73.01,13.833 73.605,13.229C74.2,12.634 74.493,11.889 74.493,11C74.493,10.12 74.2,9.375 73.605,8.78ZM69.767,9.282C70.211,8.83 70.755,8.604 71.409,8.604C72.063,8.604 72.607,8.83 73.043,9.282C73.487,9.727 73.705,10.305 73.705,11C73.705,11.696 73.487,12.274 73.043,12.718C72.607,13.171 72.063,13.397 71.409,13.397C70.755,13.397 70.211,13.171 69.767,12.718C69.331,12.266 69.113,11.696 69.113,11C69.113,10.305 69.331,9.735 69.767,9.282Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M76.345,10.263L76.312,9.106L76.345,9.106L79.396,14L80.2,14L80.2,8L79.429,8L79.429,11.512L79.463,12.668L79.429,12.668L76.513,8L75.575,8L75.575,14L76.345,14L76.345,10.263Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M47.376,10.791L44.468,10.791L44.468,11.512L46.647,11.512C46.588,12.098 46.353,12.559 45.96,12.894C45.566,13.229 45.063,13.397 44.468,13.397C43.814,13.397 43.261,13.171 42.809,12.718C42.365,12.257 42.138,11.688 42.138,11C42.138,10.313 42.365,9.743 42.809,9.282C43.261,8.83 43.814,8.604 44.468,8.604C44.803,8.604 45.122,8.662 45.415,8.788C45.708,8.914 45.943,9.09 46.127,9.316L46.68,8.763C46.429,8.478 46.11,8.26 45.717,8.101C45.323,7.942 44.912,7.866 44.468,7.866C43.596,7.866 42.859,8.168 42.256,8.771C41.652,9.375 41.351,10.12 41.351,11C41.351,11.88 41.652,12.626 42.256,13.229C42.859,13.833 43.596,14.134 44.468,14.134C45.381,14.134 46.11,13.841 46.672,13.246C47.166,12.752 47.418,12.081 47.418,11.243C47.418,11.101 47.401,10.95 47.376,10.791ZM48.524,8L48.524,14L52.027,14L52.027,13.263L49.295,13.263L49.295,11.361L51.758,11.361L51.758,10.64L49.295,10.64L49.295,8.738L52.027,8.738L52.027,8L48.524,8ZM56.953,8.738L56.953,8L52.831,8L52.831,8.738L54.507,8.738L54.507,14L55.277,14L55.277,8.738L56.953,8.738ZM60.708,8L59.937,8L59.937,14L60.708,14L60.708,8ZM65.803,8.738L65.803,8L61.68,8L61.68,8.738L63.356,8.738L63.356,14L64.127,14L64.127,8.738L65.803,8.738ZM73.605,8.78C73.01,8.168 72.281,7.866 71.409,7.866C70.537,7.866 69.808,8.168 69.213,8.771C68.618,9.366 68.325,10.112 68.325,11C68.325,11.889 68.618,12.634 69.213,13.229C69.808,13.833 70.537,14.134 71.409,14.134C72.272,14.134 73.01,13.833 73.605,13.229C74.2,12.634 74.493,11.889 74.493,11C74.493,10.12 74.2,9.375 73.605,8.78ZM69.767,9.282C70.211,8.83 70.755,8.604 71.409,8.604C72.063,8.604 72.607,8.83 73.043,9.282C73.487,9.727 73.705,10.305 73.705,11C73.705,11.696 73.487,12.274 73.043,12.718C72.607,13.171 72.063,13.397 71.409,13.397C70.755,13.397 70.211,13.171 69.767,12.718C69.331,12.266 69.113,11.696 69.113,11C69.113,10.305 69.331,9.735 69.767,9.282ZM76.346,10.263L76.312,9.106L76.346,9.106L79.396,14L80.2,14L80.2,8L79.429,8L79.429,11.512L79.463,12.668L79.429,12.668L76.513,8L75.575,8L75.575,14L76.346,14L76.346,10.263Z" style="fill:none;stroke:white;stroke-width:0.2px;"/>
|
||||
<path d="M106.936,31.001L108.802,31.001L108.802,18.499L106.936,18.499L106.936,31.001ZM123.743,23.002L121.604,28.422L121.54,28.422L119.32,23.002L117.31,23.002L120.64,30.578L118.741,34.791L120.687,34.791L125.818,23.002L123.743,23.002ZM113.16,29.581C112.55,29.581 111.697,29.275 111.697,28.519C111.697,27.554 112.759,27.184 113.675,27.184C114.495,27.184 114.882,27.361 115.38,27.602C115.235,28.76 114.238,29.581 113.16,29.581ZM113.386,22.729C112.035,22.729 110.636,23.324 110.057,24.643L111.713,25.334C112.067,24.643 112.726,24.418 113.418,24.418C114.383,24.418 115.364,24.997 115.38,26.026L115.38,26.155C115.042,25.962 114.318,25.672 113.434,25.672C111.648,25.672 109.831,26.653 109.831,28.487C109.831,30.16 111.295,31.237 112.935,31.237C114.189,31.237 114.882,30.674 115.315,30.015L115.38,30.015L115.38,30.98L117.182,30.98L117.182,26.187C117.182,23.967 115.524,22.729 113.386,22.729ZM101.854,24.524L99.2,24.524L99.2,20.239L101.854,20.239C103.249,20.239 104.041,21.394 104.041,22.382C104.041,23.351 103.249,24.524 101.854,24.524ZM101.806,18.499L97.334,18.499L97.334,31.001L99.2,31.001L99.2,26.264L101.806,26.264C103.874,26.264 105.907,24.767 105.907,22.382C105.907,19.997 103.874,18.499 101.806,18.499ZM77.424,29.583C76.135,29.583 75.056,28.503 75.056,27.022C75.056,25.523 76.135,24.428 77.424,24.428C78.697,24.428 79.696,25.523 79.696,27.022C79.696,28.503 78.697,29.583 77.424,29.583ZM79.567,23.703L79.502,23.703C79.083,23.203 78.278,22.752 77.263,22.752C75.136,22.752 73.187,24.621 73.187,27.022C73.187,29.406 75.136,31.258 77.263,31.258C78.278,31.258 79.083,30.807 79.502,30.292L79.567,30.292L79.567,30.904C79.567,32.531 78.697,33.401 77.295,33.401C76.152,33.401 75.443,32.58 75.153,31.887L73.526,32.563C73.993,33.691 75.233,35.077 77.295,35.077C79.487,35.077 81.339,33.788 81.339,30.646L81.339,23.01L79.567,23.01L79.567,23.703ZM82.628,31.001L84.497,31.001L84.497,18.499L82.628,18.499L82.628,31.001ZM87.251,26.876C87.204,25.233 88.525,24.396 89.475,24.396C90.216,24.396 90.844,24.766 91.054,25.297L87.251,26.876ZM93.051,25.459C92.697,24.508 91.618,22.752 89.411,22.752C87.219,22.752 85.399,24.476 85.399,27.005C85.399,29.39 87.204,31.258 89.62,31.258C91.569,31.258 92.697,30.066 93.165,29.374L91.714,28.407C91.231,29.116 90.571,29.583 89.62,29.583C88.669,29.583 87.993,29.148 87.558,28.294L93.245,25.942L93.051,25.459ZM47.743,24.057L47.743,25.861L52.061,25.861C51.932,26.876 51.594,27.617 51.078,28.133C50.45,28.761 49.467,29.454 47.743,29.454C45.085,29.454 43.007,27.312 43.007,24.653C43.007,21.995 45.085,19.852 47.743,19.852C49.177,19.852 50.224,20.416 50.998,21.141L52.27,19.868C51.191,18.837 49.757,18.048 47.743,18.048C44.102,18.048 41.041,21.012 41.041,24.653C41.041,28.294 44.102,31.258 47.743,31.258C49.708,31.258 51.191,30.614 52.351,29.406C53.543,28.213 53.914,26.538 53.914,25.185C53.914,24.766 53.881,24.379 53.817,24.057L47.743,24.057ZM58.822,29.583C57.533,29.583 56.421,28.52 56.421,27.005C56.421,25.475 57.533,24.428 58.822,24.428C60.111,24.428 61.223,25.475 61.223,27.005C61.223,28.52 60.111,29.583 58.822,29.583ZM58.822,22.752C56.47,22.752 54.553,24.541 54.553,27.005C54.553,29.454 56.47,31.258 58.822,31.258C61.174,31.258 63.091,29.454 63.091,27.005C63.091,24.541 61.174,22.752 58.822,22.752ZM68.135,29.583C66.847,29.583 65.735,28.52 65.735,27.005C65.735,25.475 66.847,24.428 68.135,24.428C69.424,24.428 70.536,25.475 70.536,27.005C70.536,28.52 69.424,29.583 68.135,29.583ZM68.135,22.752C65.783,22.752 63.866,24.541 63.866,27.005C63.866,29.454 65.783,31.258 68.135,31.258C70.488,31.258 72.405,29.454 72.405,27.005C72.405,24.541 70.488,22.752 68.135,22.752Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M20.717,20.425L10.07,31.725C10.071,31.727 10.071,31.729 10.072,31.731C10.398,32.959 11.519,33.862 12.849,33.862C13.381,33.862 13.88,33.718 14.308,33.466L14.342,33.446L26.326,26.531L20.717,20.425Z" style="fill:rgb(235,67,53);fill-rule:nonzero;"/>
|
||||
<path d="M31.488,18.501L31.478,18.494L26.304,15.494L20.475,20.681L26.324,26.529L31.471,23.56C32.373,23.073 32.985,22.122 32.985,21.025C32.985,19.936 32.381,18.989 31.488,18.501Z" style="fill:rgb(250,188,19);fill-rule:nonzero;"/>
|
||||
<path d="M10.07,10.278C10.006,10.514 9.972,10.761 9.972,11.018L9.972,30.985C9.972,31.242 10.005,31.49 10.07,31.725L21.083,20.714L10.07,10.278Z" style="fill:rgb(84,125,191);fill-rule:nonzero;"/>
|
||||
<path d="M20.795,21.001L26.306,15.492L14.335,8.552C13.9,8.291 13.393,8.141 12.849,8.141C11.519,8.141 10.397,9.046 10.07,10.275L10.07,10.278L20.795,21.001Z" style="fill:rgb(48,168,81);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 10 KiB |
52
.github/assets/badge-mac-app-store.svg
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 157 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M146.571,0L9.535,0C9.168,0 8.806,0 8.44,0.002C8.134,0.004 7.83,0.01 7.521,0.015C6.85,0.023 6.18,0.082 5.517,0.191C4.856,0.304 4.215,0.515 3.616,0.818C3.019,1.124 2.472,1.522 1.998,1.997C1.52,2.471 1.122,3.018 0.819,3.618C0.515,4.217 0.305,4.859 0.194,5.521C0.083,6.183 0.023,6.853 0.015,7.523C0.006,7.83 0.005,8.138 0,8.444L0,31.559C0.005,31.869 0.006,32.17 0.015,32.481C0.023,33.151 0.083,33.821 0.194,34.482C0.304,35.145 0.515,35.788 0.819,36.387C1.122,36.985 1.52,37.53 1.998,38.001C2.471,38.478 3.017,38.876 3.616,39.18C4.215,39.484 4.855,39.697 5.517,39.811C6.18,39.919 6.85,39.978 7.521,39.987C7.83,39.994 8.134,39.998 8.44,39.998C8.806,40 9.168,40 9.535,40L146.571,40C146.931,40 147.296,40 147.655,39.998C147.96,39.998 148.272,39.994 148.577,39.987C149.247,39.979 149.916,39.92 150.577,39.81C151.241,39.696 151.884,39.483 152.485,39.18C153.084,38.876 153.63,38.478 154.103,38.001C154.579,37.528 154.977,36.983 155.284,36.387C155.586,35.787 155.795,35.145 155.903,34.482C156.015,33.821 156.077,33.151 156.089,32.481C156.093,32.17 156.093,31.869 156.093,31.559C156.101,31.195 156.101,30.834 156.101,30.465L156.101,9.536C156.101,9.17 156.101,8.807 156.093,8.444C156.093,8.138 156.093,7.83 156.089,7.523C156.077,6.852 156.015,6.183 155.903,5.521C155.795,4.859 155.586,4.217 155.284,3.618C154.667,2.415 153.688,1.436 152.485,0.818C151.884,0.516 151.241,0.304 150.577,0.191C149.916,0.081 149.247,0.022 148.577,0.015C148.272,0.01 147.96,0.004 147.655,0.002C147.296,-0 146.931,-0 146.571,-0L146.571,0Z" style="fill:rgb(166,166,166);fill-rule:nonzero;"/>
|
||||
<path d="M8.445,39.125C8.14,39.125 7.843,39.121 7.541,39.114C6.914,39.106 6.29,39.052 5.671,38.951C5.095,38.852 4.537,38.667 4.015,38.403C3.498,38.142 3.026,37.798 2.618,37.387C2.204,36.98 1.859,36.508 1.597,35.99C1.333,35.469 1.149,34.91 1.054,34.333C0.951,33.713 0.896,33.086 0.888,32.458C0.881,32.247 0.873,31.545 0.873,31.545L0.873,8.444C0.873,8.444 0.882,7.753 0.888,7.55C0.895,6.922 0.951,6.297 1.053,5.678C1.149,5.099 1.332,4.539 1.597,4.016C1.857,3.498 2.2,3.026 2.612,2.618C3.023,2.206 3.496,1.861 4.014,1.595C4.535,1.332 5.092,1.149 5.667,1.051C6.288,0.95 6.915,0.895 7.543,0.887L8.445,0.875L147.65,0.875L148.563,0.888C149.186,0.895 149.807,0.949 150.422,1.05C151.003,1.149 151.566,1.334 152.093,1.598C153.13,2.133 153.975,2.979 154.508,4.018C154.768,4.538 154.949,5.094 155.043,5.667C155.147,6.291 155.205,6.922 155.217,7.554C155.22,7.837 155.22,8.142 155.22,8.444C155.228,8.819 155.228,9.176 155.228,9.536L155.228,30.465C155.228,30.828 155.228,31.183 155.22,31.54C155.22,31.865 155.22,32.163 155.216,32.47C155.204,33.091 155.147,33.71 155.045,34.323C154.952,34.904 154.769,35.468 154.505,35.993C154.241,36.506 153.898,36.973 153.489,37.379C153.081,37.793 152.608,38.138 152.09,38.401C151.565,38.667 151.002,38.853 150.422,38.951C149.804,39.052 149.179,39.107 148.553,39.114C148.26,39.121 147.953,39.125 147.655,39.125L146.571,39.127L8.445,39.125Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g id="_Group_">
|
||||
<g id="_Group_2_" serif:id="_Group_2">
|
||||
<g id="_Group_3_" serif:id="_Group_3">
|
||||
<g id="_Group_4_" serif:id="_Group_4">
|
||||
<path id="_Path_" d="M24.769,20.301C24.791,18.606 25.682,17.036 27.125,16.149C26.21,14.842 24.729,14.041 23.134,13.991C21.455,13.815 19.827,14.996 18.971,14.996C18.099,14.996 16.782,14.008 15.363,14.038C13.498,14.098 11.797,15.135 10.89,16.766C8.956,20.114 10.399,25.035 12.251,27.742C13.178,29.067 14.261,30.547 15.679,30.495C17.066,30.437 17.584,29.61 19.258,29.61C20.917,29.61 21.403,30.495 22.849,30.462C24.338,30.437 25.275,29.13 26.17,27.792C26.836,26.848 27.348,25.804 27.688,24.7C25.924,23.954 24.771,22.216 24.769,20.301Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path id="_Path_2_" serif:id="_Path_2" d="M22.037,12.211C22.848,11.237 23.249,9.984 23.152,8.72C21.912,8.85 20.766,9.443 19.944,10.38C19.132,11.304 18.721,12.514 18.8,13.741C20.056,13.754 21.25,13.189 22.037,12.211Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M46.149,30.496L46.149,21.356L46.088,21.356L42.345,30.401L40.917,30.401L37.164,21.356L37.104,21.356L37.104,30.496L35.348,30.496L35.348,18.078L37.578,18.078L41.596,27.88L41.665,27.88L45.675,18.078L47.913,18.078L47.913,30.496L46.149,30.496Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M49.396,27.923C49.396,26.34 50.609,25.384 52.761,25.255L55.24,25.117L55.24,24.429C55.24,23.422 54.577,22.853 53.449,22.853C52.588,22.739 51.768,23.289 51.547,24.128L49.809,24.128C49.861,22.492 51.384,21.331 53.501,21.331C55.661,21.331 57.089,22.51 57.089,24.291L57.089,30.496L55.308,30.496L55.308,29.007L55.265,29.007C54.685,30.034 53.587,30.666 52.408,30.651C52.319,30.66 52.23,30.664 52.14,30.664C50.636,30.664 49.398,29.427 49.396,27.923ZM55.24,27.105L55.24,26.408L53.01,26.546C51.9,26.615 51.272,27.097 51.272,27.871C51.272,28.663 51.926,29.18 52.924,29.18C52.973,29.183 53.022,29.185 53.071,29.185C54.227,29.185 55.191,28.261 55.24,27.105L55.24,27.105Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M64.893,24.558C64.726,23.536 63.791,22.805 62.759,22.889C61.331,22.889 60.384,24.085 60.384,25.97C60.384,27.897 61.339,29.059 62.776,29.059C63.795,29.161 64.729,28.443 64.893,27.433L66.683,27.433C66.453,29.367 64.699,30.787 62.759,30.608C60.177,30.608 58.491,28.844 58.491,25.97C58.491,23.155 60.177,21.331 62.742,21.331C64.696,21.165 66.451,22.608 66.667,24.558L64.893,24.558Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M78.759,27.14L74.026,27.14L72.889,30.496L70.884,30.496L75.368,18.078L77.451,18.078L81.934,30.496L79.895,30.496L78.759,27.14ZM74.516,25.591L78.268,25.591L76.419,20.144L76.367,20.144L74.516,25.591Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M91.617,25.97C91.617,28.783 90.111,30.591 87.838,30.591C86.666,30.652 85.556,30.035 84.99,29.007L84.947,29.007L84.947,33.491L83.088,33.491L83.088,21.442L84.887,21.442L84.887,22.948L84.921,22.948C85.513,21.926 86.623,21.31 87.804,21.348C90.102,21.348 91.617,23.164 91.617,25.97ZM89.707,25.97C89.707,24.137 88.759,22.932 87.314,22.932C85.894,22.932 84.939,24.162 84.939,25.97C84.939,27.794 85.894,29.016 87.314,29.016C88.759,29.016 89.707,27.819 89.707,25.97Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M101.582,25.97C101.582,28.783 100.076,30.591 97.803,30.591C96.631,30.652 95.521,30.035 94.955,29.007L94.912,29.007L94.912,33.491L93.053,33.491L93.053,21.442L94.852,21.442L94.852,22.948L94.886,22.948C95.478,21.926 96.588,21.31 97.769,21.348C100.067,21.348 101.582,23.164 101.582,25.97ZM99.671,25.97C99.671,24.137 98.724,22.932 97.279,22.932C95.859,22.932 94.904,24.162 94.904,25.97C94.904,27.794 95.859,29.016 97.279,29.016C98.724,29.016 99.671,27.819 99.671,25.97L99.671,25.97Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M108.168,27.036C108.305,28.268 109.502,29.076 111.136,29.076C112.703,29.076 113.83,28.268 113.83,27.157C113.83,26.193 113.15,25.616 111.541,25.221L109.931,24.833C107.651,24.282 106.592,23.216 106.592,21.485C106.592,19.343 108.459,17.871 111.111,17.871C113.735,17.871 115.534,19.343 115.594,21.485L113.718,21.485C113.606,20.246 112.582,19.498 111.084,19.498C109.587,19.498 108.563,20.255 108.563,21.356C108.563,22.234 109.217,22.751 110.818,23.146L112.186,23.482C114.734,24.085 115.792,25.108 115.792,26.925C115.792,29.248 113.942,30.703 110.999,30.703C108.245,30.703 106.385,29.282 106.265,27.036L108.168,27.036Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M119.803,19.3L119.803,21.442L121.525,21.442L121.525,22.914L119.803,22.914L119.803,27.905C119.803,28.681 120.148,29.042 120.905,29.042C121.109,29.038 121.313,29.024 121.516,28.999L121.516,30.462C121.176,30.525 120.83,30.554 120.484,30.548C118.651,30.548 117.936,29.859 117.936,28.103L117.936,22.914L116.62,22.914L116.62,21.442L117.936,21.442L117.936,19.3L119.803,19.3Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M122.521,25.97C122.521,23.121 124.199,21.331 126.815,21.331C129.44,21.331 131.11,23.121 131.11,25.97C131.11,28.826 129.449,30.608 126.815,30.608C124.182,30.608 122.521,28.826 122.521,25.97ZM129.216,25.97C129.216,24.016 128.321,22.862 126.815,22.862C125.309,22.862 124.414,24.024 124.414,25.97C124.414,27.932 125.309,29.076 126.815,29.076C128.321,29.076 129.216,27.932 129.216,25.97L129.216,25.97Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M132.643,21.442L134.416,21.442L134.416,22.983L134.459,22.983C134.705,21.995 135.618,21.309 136.636,21.348C136.85,21.347 137.064,21.37 137.273,21.417L137.273,23.155C137.003,23.073 136.721,23.035 136.438,23.043C136.413,23.042 136.387,23.041 136.362,23.041C135.335,23.041 134.489,23.887 134.489,24.914C134.489,24.985 134.493,25.056 134.501,25.126L134.501,30.496L132.643,30.496L132.643,21.442Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M145.84,27.837C145.59,29.48 143.99,30.608 141.942,30.608C139.308,30.608 137.673,28.844 137.673,26.013C137.673,23.173 139.317,21.331 141.864,21.331C144.369,21.331 145.944,23.052 145.944,25.797L145.944,26.434L139.549,26.434L139.549,26.546C139.543,26.615 139.54,26.684 139.54,26.754C139.54,28.047 140.605,29.112 141.898,29.112C141.927,29.112 141.956,29.111 141.985,29.11C142.884,29.195 143.738,28.675 144.076,27.837L145.84,27.837ZM139.558,25.135L144.084,25.135C144.087,25.094 144.088,25.054 144.088,25.014C144.088,23.819 143.105,22.836 141.911,22.836C141.895,22.836 141.879,22.837 141.864,22.837C141.859,22.837 141.855,22.837 141.85,22.837C140.593,22.837 139.558,23.872 139.558,25.129C139.558,25.131 139.558,25.133 139.558,25.135L139.558,25.135Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="_Group_5_" serif:id="_Group_5">
|
||||
<g>
|
||||
<path d="M37.826,8.731C37.889,8.726 37.952,8.724 38.015,8.724C39.463,8.724 40.655,9.916 40.655,11.364C40.655,11.475 40.648,11.586 40.634,11.696C40.634,13.602 39.604,14.698 37.826,14.698L35.671,14.698L35.671,8.731L37.826,8.731ZM36.598,13.854L37.723,13.854C37.76,13.856 37.797,13.857 37.835,13.857C38.864,13.857 39.71,13.011 39.71,11.981C39.71,11.89 39.704,11.799 39.69,11.708C39.702,11.623 39.708,11.538 39.708,11.452C39.708,10.42 38.859,9.571 37.827,9.571C37.792,9.571 37.757,9.572 37.723,9.574L36.598,9.574L36.598,13.854Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M41.681,12.444C41.674,12.377 41.671,12.309 41.671,12.241C41.671,11.071 42.634,10.108 43.804,10.108C44.974,10.108 45.937,11.071 45.937,12.241C45.937,12.309 45.934,12.377 45.928,12.444C45.934,12.513 45.938,12.582 45.938,12.651C45.938,13.822 44.975,14.785 43.804,14.785C42.634,14.785 41.671,13.822 41.671,12.651C41.671,12.582 41.674,12.513 41.681,12.444ZM45.014,12.444C45.014,11.468 44.575,10.897 43.806,10.897C43.033,10.897 42.599,11.468 42.599,12.444C42.599,13.428 43.033,13.995 43.806,13.995C44.575,13.995 45.014,13.424 45.014,12.444L45.014,12.444Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M51.573,14.698L50.651,14.698L49.721,11.381L49.65,11.381L48.724,14.698L47.811,14.698L46.569,10.195L47.471,10.195L48.277,13.631L48.344,13.631L49.27,10.195L50.122,10.195L51.048,13.631L51.118,13.631L51.921,10.195L52.81,10.195L51.573,14.698Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M53.854,10.195L54.709,10.195L54.709,10.91L54.775,10.91C55.006,10.385 55.547,10.061 56.119,10.108C56.156,10.105 56.192,10.104 56.229,10.104C57.032,10.104 57.694,10.765 57.694,11.568C57.694,11.64 57.688,11.712 57.678,11.783L57.678,14.698L56.789,14.698L56.789,12.006C56.789,11.282 56.475,10.922 55.817,10.922C55.801,10.922 55.785,10.921 55.769,10.921C55.203,10.921 54.736,11.388 54.736,11.954C54.736,11.991 54.738,12.027 54.742,12.063L54.742,14.698L53.854,14.698L53.854,10.195Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<rect x="59.094" y="8.437" width="0.889" height="6.261" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M61.218,12.444C61.211,12.377 61.208,12.309 61.208,12.241C61.208,11.071 62.171,10.108 63.341,10.108C64.512,10.108 65.475,11.071 65.475,12.241C65.475,12.309 65.471,12.377 65.465,12.444C65.472,12.513 65.475,12.582 65.475,12.651C65.475,13.822 64.512,14.785 63.341,14.785C62.171,14.785 61.208,13.822 61.208,12.651C61.208,12.582 61.211,12.513 61.218,12.444ZM64.551,12.444C64.551,11.468 64.112,10.897 63.343,10.897C62.57,10.897 62.136,11.468 62.136,12.444C62.136,13.428 62.57,13.995 63.343,13.995C64.112,13.995 64.551,13.424 64.551,12.444L64.551,12.444Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M66.4,13.424C66.4,12.614 67.004,12.146 68.075,12.08L69.295,12.01L69.295,11.621C69.295,11.146 68.98,10.877 68.373,10.877C67.877,10.877 67.533,11.059 67.435,11.377L66.574,11.377C66.665,10.604 67.393,10.108 68.414,10.108C69.543,10.108 70.18,10.67 70.18,11.621L70.18,14.698L69.324,14.698L69.324,14.065L69.254,14.065C68.964,14.526 68.446,14.797 67.901,14.772C67.855,14.777 67.808,14.779 67.761,14.779C67.016,14.779 66.403,14.169 66.4,13.424ZM69.295,13.04L69.295,12.663L68.195,12.733C67.575,12.775 67.294,12.986 67.294,13.383C67.294,13.788 67.646,14.024 68.129,14.024C68.164,14.028 68.2,14.029 68.236,14.029C68.791,14.029 69.257,13.594 69.295,13.04Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M71.348,12.444C71.348,11.021 72.079,10.12 73.217,10.12C73.79,10.094 74.33,10.402 74.598,10.91L74.664,10.91L74.664,8.437L75.553,8.437L75.553,14.698L74.701,14.698L74.701,13.986L74.631,13.986C74.343,14.49 73.797,14.793 73.217,14.772C72.071,14.772 71.348,13.871 71.348,12.444ZM72.266,12.444C72.266,13.399 72.716,13.974 73.469,13.974C74.218,13.974 74.681,13.391 74.681,12.448C74.681,11.51 74.213,10.918 73.469,10.918C72.721,10.918 72.266,11.497 72.266,12.444L72.266,12.444Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M79.23,12.444C79.223,12.377 79.22,12.309 79.22,12.241C79.22,11.071 80.183,10.108 81.353,10.108C82.524,10.108 83.487,11.071 83.487,12.241C83.487,12.309 83.484,12.377 83.477,12.444C83.484,12.513 83.487,12.582 83.487,12.651C83.487,13.821 82.524,14.785 81.353,14.785C80.183,14.785 79.219,13.821 79.219,12.651C79.219,12.582 79.223,12.513 79.23,12.444ZM82.563,12.444C82.563,11.468 82.124,10.897 81.355,10.897C80.582,10.897 80.148,11.468 80.148,12.444C80.148,13.428 80.582,13.995 81.355,13.995C82.124,13.995 82.563,13.424 82.563,12.444L82.563,12.444Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M84.669,10.195L85.525,10.195L85.525,10.91L85.591,10.91C85.822,10.385 86.363,10.061 86.935,10.108C86.972,10.105 87.008,10.104 87.045,10.104C87.848,10.104 88.509,10.765 88.509,11.568C88.509,11.64 88.504,11.712 88.494,11.783L88.494,14.698L87.605,14.698L87.605,12.006C87.605,11.282 87.291,10.922 86.633,10.922C86.617,10.922 86.601,10.921 86.585,10.921C86.019,10.921 85.552,11.388 85.552,11.954C85.552,11.991 85.554,12.027 85.558,12.063L85.558,14.698L84.669,14.698L84.669,10.195Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M93.515,9.074L93.515,10.215L94.491,10.215L94.491,10.964L93.515,10.964L93.515,13.279C93.515,13.751 93.709,13.958 94.152,13.958C94.265,13.957 94.378,13.95 94.491,13.937L94.491,14.677C94.331,14.706 94.169,14.721 94.007,14.723C93.019,14.723 92.626,14.375 92.626,13.507L92.626,10.964L91.911,10.964L91.911,10.215L92.626,10.215L92.626,9.074L93.515,9.074Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M95.705,8.437L96.585,8.437L96.585,10.918L96.656,10.918C96.897,10.388 97.448,10.065 98.029,10.112C98.056,10.11 98.082,10.11 98.109,10.11C98.923,10.11 99.593,10.779 99.593,11.593C99.593,11.659 99.588,11.725 99.58,11.791L99.58,14.698L98.69,14.698L98.69,12.01C98.69,11.291 98.355,10.926 97.727,10.926C97.699,10.924 97.67,10.923 97.641,10.923C97.064,10.923 96.589,11.398 96.589,11.975C96.589,12.006 96.591,12.037 96.593,12.068L96.593,14.698L95.705,14.698L95.705,8.437Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M104.761,13.482C104.513,14.328 103.687,14.88 102.81,14.785C102.792,14.785 102.774,14.785 102.756,14.785C101.634,14.785 100.711,13.862 100.711,12.74C100.711,12.647 100.717,12.553 100.73,12.46C100.718,12.369 100.712,12.277 100.712,12.185C100.712,11.045 101.649,10.108 102.788,10.108C102.794,10.108 102.8,10.108 102.806,10.108C104.059,10.108 104.815,10.964 104.815,12.378L104.815,12.688L101.635,12.688L101.635,12.738C101.632,12.771 101.631,12.804 101.631,12.838C101.631,13.491 102.168,14.028 102.821,14.028C102.826,14.028 102.83,14.028 102.834,14.028C103.268,14.08 103.693,13.864 103.906,13.482L104.761,13.482ZM101.635,12.031L103.91,12.031C103.912,12.004 103.913,11.977 103.913,11.95C103.913,11.354 103.422,10.864 102.826,10.864C102.818,10.864 102.81,10.864 102.801,10.864C102.796,10.864 102.792,10.864 102.787,10.864C102.155,10.864 101.635,11.384 101.635,12.016C101.635,12.021 101.635,12.026 101.635,12.031L101.635,12.031Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 17 KiB |
23
.github/assets/badge-web.svg
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 135 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<path d="M130.2,40L4.73,40C2.137,39.995 0.005,37.863 -0,35.27L0,4.73C-0,2.135 2.135,0 4.73,0L130.2,0C132.807,-0 134.962,2.123 135,4.73L135,35.27C134.957,37.875 132.805,39.995 130.2,40Z" style="fill:rgb(166,166,166);fill-rule:nonzero;"/>
|
||||
<path d="M134,35.27C134,37.371 132.271,39.1 130.17,39.1L4.73,39.1C2.627,39.1 0.895,37.373 0.89,35.27L0.89,4.72C0.895,2.617 2.627,0.89 4.73,0.89L130.2,0.89C132.29,0.906 134,2.63 134,4.72L134,35.27Z" style="fill-rule:nonzero;"/>
|
||||
<path d="M40.56,25.26L41.82,22.08L45.45,22.08L43.73,17.26L45.88,11.81L52.05,28.19L47.5,28.19L46.5,25.26L40.56,25.26Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M36.68,28.19L43.29,11.81L38.91,11.81L34.39,22.4L31.18,11.81L27.81,11.81L24.36,22.4L21.93,17.57L19.73,24.35L22,28.19L26.31,28.19L29.43,18.7L32.43,28.19L36.68,28.19Z" style="fill:rgb(90,15,200);fill-rule:nonzero;"/>
|
||||
<path d="M12.7,22.57L15.4,22.57C16.136,22.582 16.871,22.488 17.58,22.29L18.28,20.14L20.23,14.14C20.08,13.902 19.91,13.678 19.72,13.47C18.57,12.302 16.965,11.695 15.33,11.81L8.55,11.81L8.55,28.19L12.7,28.19L12.7,22.57ZM16.27,15.57C16.674,15.994 16.888,16.565 16.86,17.15C16.892,17.723 16.706,18.288 16.34,18.73C15.77,19.23 15.014,19.466 14.26,19.38L12.7,19.38L12.7,15L14.27,15C14.987,14.922 15.706,15.13 16.27,15.58L16.27,15.57Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M61.25,14.45L61.25,8.74L61.91,8.74L61.91,13.85L64.43,13.85L64.43,14.45L61.25,14.45Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M67.94,14.45L67.81,13.84C67.645,14.069 67.43,14.258 67.18,14.39C66.925,14.489 66.653,14.536 66.38,14.53C66.017,14.55 65.66,14.432 65.38,14.2C65.131,13.957 64.999,13.617 65.02,13.27C65.02,12.4 65.71,11.95 67.1,11.91L67.82,11.91L67.82,11.64C67.842,11.376 67.768,11.113 67.61,10.9C67.421,10.725 67.167,10.637 66.91,10.66C66.489,10.68 66.076,10.789 65.7,10.98L65.5,10.49C65.719,10.366 65.955,10.275 66.2,10.22C66.444,10.152 66.697,10.119 66.95,10.12C67.359,10.087 67.766,10.208 68.09,10.46C68.358,10.757 68.492,11.151 68.46,11.55L68.46,14.47L67.94,14.45ZM66.47,14C66.836,14.03 67.198,13.906 67.47,13.66C67.712,13.413 67.839,13.075 67.82,12.73L67.82,12.35L67.17,12.35C66.783,12.339 66.399,12.422 66.05,12.59C65.827,12.738 65.697,12.993 65.71,13.26C65.696,13.459 65.773,13.654 65.92,13.79C66.075,13.918 66.269,13.992 66.47,14Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M70.36,10.17L70.36,13C70.337,13.281 70.423,13.56 70.6,13.78C70.801,13.964 71.068,14.058 71.34,14.04C71.712,14.077 72.081,13.94 72.34,13.67C72.576,13.317 72.685,12.893 72.65,12.47L72.65,10.17L73.3,10.17L73.3,14.45L72.76,14.45L72.67,13.88C72.539,14.092 72.348,14.259 72.12,14.36C71.866,14.476 71.589,14.534 71.31,14.53C70.887,14.564 70.467,14.431 70.14,14.16C69.841,13.85 69.682,13.43 69.7,13L69.7,10.2L70.36,10.17Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M77.59,14.45L77.59,11.68C77.613,11.399 77.527,11.12 77.35,10.9C77.149,10.716 76.882,10.622 76.61,10.64C76.238,10.603 75.869,10.74 75.61,11.01C75.37,11.361 75.26,11.786 75.3,12.21L75.3,14.45L74.65,14.45L74.65,10.17L75.18,10.17L75.28,10.76C75.41,10.545 75.602,10.374 75.83,10.27C76.079,10.148 76.353,10.087 76.63,10.09C77.055,10.059 77.475,10.195 77.8,10.47C78.09,10.795 78.232,11.226 78.19,11.66L78.19,14.45L77.59,14.45Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M81.28,14.53C80.746,14.573 80.219,14.379 79.84,14C79.474,13.543 79.292,12.965 79.33,12.38C79.294,11.782 79.479,11.191 79.85,10.72C80.231,10.314 80.774,10.098 81.33,10.13C81.535,10.134 81.739,10.157 81.94,10.2C82.11,10.23 82.275,10.284 82.43,10.36L82.23,10.91C82.077,10.848 81.92,10.798 81.76,10.76C81.612,10.731 81.461,10.714 81.31,10.71C80.44,10.71 80,11.26 80,12.37C79.974,12.797 80.087,13.221 80.32,13.58C80.56,13.881 80.937,14.04 81.32,14C81.698,13.998 82.072,13.92 82.42,13.77L82.42,14.35C82.061,14.504 81.669,14.566 81.28,14.53Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M86.31,14.45L86.31,11.68C86.333,11.399 86.247,11.12 86.07,10.9C85.869,10.716 85.602,10.622 85.33,10.64C84.958,10.608 84.591,10.744 84.33,11.01C84.093,11.363 83.983,11.786 84.02,12.21L84.02,14.45L83.37,14.45L83.37,8.37L84,8.37L84,10.21C84.013,10.393 84.013,10.577 84,10.76C84.135,10.556 84.321,10.39 84.54,10.28C84.792,10.157 85.07,10.096 85.35,10.1C85.776,10.068 86.199,10.2 86.53,10.47C86.846,10.783 87.017,11.215 87,11.66L87,14.45L86.31,14.45Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M93,14.45L92.87,13.84C92.704,14.073 92.485,14.261 92.23,14.39C91.979,14.49 91.71,14.537 91.44,14.53C91.077,14.552 90.719,14.434 90.44,14.2C90.191,13.957 90.059,13.617 90.08,13.27C90.08,12.4 90.77,11.95 92.15,11.91L92.88,11.91L92.88,11.64C92.909,11.374 92.829,11.107 92.66,10.9C92.476,10.723 92.224,10.635 91.97,10.66C91.548,10.678 91.135,10.787 90.76,10.98L90.56,10.49C90.776,10.368 91.008,10.277 91.25,10.22C91.498,10.152 91.753,10.119 92.01,10.12C92.416,10.084 92.821,10.206 93.14,10.46C93.413,10.754 93.547,11.151 93.51,11.55L93.51,14.47L93,14.45ZM91.54,14C91.889,14.016 92.23,13.894 92.49,13.66C92.73,13.412 92.853,13.074 92.83,12.73L92.83,12.35L92.19,12.35C91.803,12.339 91.419,12.422 91.07,12.59C90.844,12.735 90.713,12.992 90.73,13.26C90.716,13.459 90.793,13.654 90.94,13.79C91.108,13.931 91.321,14.005 91.54,14Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M97.58,13.28C97.596,13.646 97.426,13.996 97.13,14.21C96.757,14.444 96.32,14.556 95.88,14.53C95.424,14.554 94.97,14.461 94.56,14.26L94.56,13.66C94.974,13.876 95.433,13.993 95.9,14C96.171,14.015 96.44,13.956 96.68,13.83C96.858,13.732 96.966,13.543 96.96,13.34C96.957,13.171 96.876,13.012 96.74,12.91C96.477,12.731 96.191,12.59 95.89,12.49C95.581,12.391 95.283,12.26 95,12.1C94.851,12.006 94.724,11.879 94.63,11.73C94.542,11.575 94.497,11.399 94.5,11.22C94.516,10.88 94.705,10.57 95,10.4C95.346,10.173 95.757,10.064 96.17,10.09C96.634,10.094 97.093,10.189 97.52,10.37L97.29,10.9C96.921,10.736 96.524,10.647 96.12,10.64C95.881,10.621 95.642,10.669 95.43,10.78C95.282,10.858 95.189,11.013 95.19,11.18C95.188,11.284 95.219,11.386 95.28,11.47C95.355,11.566 95.451,11.645 95.56,11.7C95.802,11.825 96.052,11.932 96.31,12.02C96.68,12.133 97.021,12.324 97.31,12.58C97.487,12.769 97.584,13.021 97.58,13.28Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M71,28.45L69.23,28.45L67.53,22.45C67.46,22.19 67.37,21.82 67.26,21.33C67.15,20.84 67.08,20.5 67.06,20.33C67.06,20.63 66.94,21 66.84,21.47C66.74,21.94 66.65,22.28 66.58,22.47L64.93,28.4L63.15,28.4L61.86,23.4L60.54,18.4L62.21,18.4L63.64,24.22C63.86,25.16 64.02,25.98 64.12,26.7C64.12,26.31 64.25,25.88 64.35,25.4C64.45,24.92 64.54,24.53 64.62,24.24L66.25,18.4L67.87,18.4L69.53,24.26C69.733,25.084 69.89,25.919 70,26.76C70.105,25.92 70.269,25.088 70.49,24.27L72,18.46L73.66,18.46L71,28.45Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M78.15,28.59C77.134,28.657 76.135,28.294 75.4,27.59C74.701,26.819 74.34,25.799 74.4,24.76C74.341,23.707 74.668,22.669 75.32,21.84C75.965,21.125 76.898,20.735 77.86,20.78C78.74,20.735 79.598,21.066 80.22,21.69C80.83,22.378 81.143,23.282 81.09,24.2L81.09,25L76.09,25C76.077,25.621 76.291,26.225 76.69,26.7C77.11,27.111 77.684,27.325 78.27,27.29C78.69,27.294 79.11,27.251 79.52,27.16C79.947,27.065 80.363,26.924 80.76,26.74L80.76,28.05C80.382,28.231 79.982,28.362 79.57,28.44C79.103,28.538 78.627,28.588 78.15,28.59ZM77.86,22C77.399,21.978 76.95,22.157 76.63,22.49C76.296,22.886 76.102,23.382 76.08,23.9L79.51,23.9C79.537,23.388 79.377,22.883 79.06,22.48C78.75,22.152 78.311,21.976 77.86,22Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M86.78,20.75C87.632,20.705 88.454,21.079 88.98,21.75C89.557,22.595 89.835,23.609 89.77,24.63C89.835,25.656 89.553,26.674 88.97,27.52C88.417,28.176 87.602,28.555 86.745,28.555C85.888,28.555 85.073,28.176 84.52,27.52L84.42,27.52L84.12,28.41L82.92,28.41L82.92,17.82L84.52,17.82L84.52,21.88L84.58,21.88C85.073,21.154 85.903,20.728 86.78,20.75ZM86.36,22.07C85.829,22.023 85.307,22.235 84.96,22.64C84.627,23.219 84.474,23.884 84.52,24.55L84.52,24.66C84.467,25.355 84.62,26.051 84.96,26.66C85.301,27.094 85.84,27.327 86.39,27.28C86.913,27.301 87.409,27.042 87.69,26.6C88.026,25.99 88.179,25.295 88.13,24.6C88.13,22.93 87.54,22.07 86.36,22.07Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M101.65,28.45L100.65,25.68L96.83,25.68L95.83,28.45L94.13,28.45L97.87,18.45L99.65,18.45L103.38,28.45L101.65,28.45ZM100.22,24.27L99.28,21.55C99.21,21.37 99.12,21.08 99,20.69C98.88,20.3 98.8,20.01 98.75,19.83C98.612,20.452 98.431,21.063 98.21,21.66L97.31,24.27L100.22,24.27Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M108.37,28.59C107.509,28.641 106.675,28.267 106.14,27.59L106,27.59C106.07,28.22 106.1,28.59 106.1,28.75L106.1,31.85L104.49,31.85L104.49,20.89L105.79,20.89C105.79,21.03 105.9,21.37 106.02,21.89L106.1,21.89C106.592,21.131 107.456,20.691 108.36,20.74C109.211,20.698 110.032,21.071 110.56,21.74C111.137,22.585 111.415,23.599 111.35,24.62C111.409,25.645 111.128,26.661 110.55,27.51C110.04,28.199 109.227,28.601 108.37,28.59ZM108,22.07C107.471,22.022 106.95,22.23 106.6,22.63C106.264,23.163 106.11,23.792 106.16,24.42L106.16,24.66C106.107,25.355 106.26,26.051 106.6,26.66C106.939,27.097 107.479,27.331 108.03,27.28C108.549,27.298 109.04,27.034 109.31,26.59C109.645,25.997 109.802,25.32 109.76,24.64C109.802,23.97 109.646,23.302 109.31,22.72C109.019,22.288 108.52,22.041 108,22.07Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M117.09,28.59C116.229,28.641 115.395,28.267 114.86,27.59L114.77,27.59C114.83,28.22 114.86,28.59 114.86,28.75L114.86,31.85L113.26,31.85L113.26,20.89L114.55,20.89C114.55,21.03 114.67,21.37 114.78,21.89L114.86,21.89C115.354,21.132 116.217,20.693 117.12,20.74C117.972,20.695 118.794,21.069 119.32,21.74C119.897,22.585 120.175,23.599 120.11,24.62C120.169,25.645 119.888,26.661 119.31,27.51C118.791,28.21 117.961,28.614 117.09,28.59ZM116.7,22.07C116.171,22.022 115.65,22.23 115.3,22.63C114.964,23.163 114.81,23.792 114.86,24.42L114.86,24.66C114.807,25.355 114.96,26.051 115.3,26.66C115.641,27.094 116.18,27.327 116.73,27.28C117.249,27.298 117.74,27.034 118.01,26.59C118.345,25.997 118.502,25.32 118.46,24.64C118.505,23.971 118.352,23.303 118.02,22.72C117.723,22.29 117.222,22.043 116.7,22.07Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 10 KiB |
31
.github/assets/badge-windows-store.svg
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 864 312" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g id="Layer_2">
|
||||
<rect x="2.3" y="2.3" width="859.5" height="307.5"/>
|
||||
<path d="M4.5,4.5L859.5,4.5L859.5,307.5L4.5,307.5L4.5,4.5ZM0,312L864,312L864,0L0,0L0,312Z" style="fill:rgb(210,210,210);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g id="Layer_1">
|
||||
<rect x="70.5" y="68.6" width="83.8" height="83.8" style="fill:rgb(242,80,34);"/>
|
||||
<rect x="163" y="68.6" width="83.8" height="83.8" style="fill:rgb(127,186,0);"/>
|
||||
<rect x="70.5" y="161" width="83.8" height="83.8" style="fill:rgb(0,164,239);"/>
|
||||
<rect x="163" y="161" width="83.8" height="83.8" style="fill:rgb(255,185,0);"/>
|
||||
<path d="M408.3,163C408.3,160.5 409.2,158.5 411,156.8C412.8,155.1 414.9,154.3 417.4,154.3C420,154.3 422.2,155.2 423.9,156.9C425.6,158.6 426.5,160.7 426.5,163C426.5,165.4 425.6,167.5 423.8,169.1C422,170.8 419.9,171.6 417.3,171.6C414.7,171.6 412.6,170.8 410.8,169.1C409.2,167.4 408.3,165.4 408.3,163M424.8,244.8L409.9,244.8L409.9,181.3L424.8,181.3L424.8,244.8Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M470.2,233.9C472.4,233.9 474.9,233.4 477.6,232.4C480.3,231.4 482.7,230 485,228.3L485,242.2C482.6,243.6 479.9,244.6 476.9,245.3C473.9,246 470.5,246.4 466.9,246.4C457.6,246.4 450,243.4 444.1,237.5C438.2,231.6 435.3,224 435.3,214.9C435.3,204.7 438.3,196.3 444.3,189.7C450.3,183.1 458.7,179.8 469.7,179.8C472.5,179.8 475.3,180.2 478.2,180.9C481.1,181.6 483.3,182.5 485,183.4L485,197.7C482.7,196 480.3,194.7 477.9,193.8C475.5,192.9 473,192.4 470.5,192.4C464.6,192.4 459.9,194.3 456.2,198.1C452.6,201.9 450.8,207.1 450.8,213.6C450.8,220 452.5,225 456,228.6C459.5,232.2 464.2,233.9 470.2,233.9" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M527.5,180.3C528.7,180.3 529.8,180.4 530.7,180.5C531.6,180.7 532.5,180.9 533.1,181.1L533.1,196.2C532.3,195.6 531.2,195.1 529.7,194.6C528.2,194.1 526.4,193.8 524.2,193.8C520.5,193.8 517.4,195.3 514.9,198.4C512.4,201.5 511.1,206.2 511.1,212.7L511.1,244.8L496.2,244.8L496.2,181.3L511.1,181.3L511.1,191.3L511.3,191.3C512.7,187.8 514.7,185.1 517.5,183.2C520.3,181.3 523.6,180.3 527.5,180.3" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M533.9,214C533.9,203.5 536.9,195.2 542.8,189C548.7,182.9 557,179.8 567.5,179.8C577.4,179.8 585.2,182.8 590.8,188.7C596.4,194.6 599.2,202.6 599.2,212.6C599.2,222.9 596.2,231.1 590.3,237.2C584.4,243.3 576.3,246.3 566.1,246.3C556.3,246.3 548.4,243.4 542.7,237.6C536.8,231.9 533.9,224 533.9,214M549.5,213.5C549.5,220.1 551,225.2 554,228.7C557,232.2 561.3,233.9 566.9,233.9C572.3,233.9 576.5,232.2 579.3,228.7C582.1,225.2 583.6,220 583.6,213.1C583.6,206.3 582.1,201.1 579.2,197.6C576.3,194.1 572.1,192.4 566.8,192.4C561.3,192.4 557.1,194.2 554,197.9C551,201.6 549.5,206.7 549.5,213.5" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M621.4,198C621.4,200.1 622.1,201.8 623.4,203C624.8,204.2 627.8,205.7 632.4,207.6C638.4,210 642.6,212.7 645,215.7C647.4,218.7 648.6,222.3 648.6,226.5C648.6,232.5 646.3,237.3 641.7,240.9C637.1,244.5 630.9,246.3 623.1,246.3C620.5,246.3 617.6,246 614.4,245.3C611.2,244.7 608.5,243.8 606.3,242.9L606.3,228.2C609,230.1 611.9,231.6 615.1,232.7C618.2,233.8 621.1,234.4 623.6,234.4C627,234.4 629.5,233.9 631.1,233C632.7,232.1 633.5,230.5 633.5,228.2C633.5,226.1 632.7,224.4 631,223C629.3,221.6 626.2,219.9 621.5,218.1C616,215.8 612.1,213.2 609.8,210.3C607.5,207.4 606.3,203.7 606.3,199.3C606.3,193.6 608.6,188.9 613.1,185.2C617.6,181.5 623.5,179.7 630.8,179.7C633,179.7 635.5,179.9 638.3,180.4C641.1,180.9 643.4,181.5 645.2,182.3L645.2,196.5C643.2,195.2 640.9,194.1 638.3,193.1C635.7,192.2 633,191.7 630.5,191.7C627.7,191.7 625.4,192.3 623.9,193.4C622.2,194.5 621.4,196.1 621.4,198" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M655.2,214C655.2,203.5 658.2,195.2 664.1,189C670,182.9 678.3,179.8 688.8,179.8C698.7,179.8 706.5,182.8 712.1,188.7C717.7,194.6 720.5,202.6 720.5,212.6C720.5,222.9 717.5,231.1 711.6,237.2C705.7,243.3 697.6,246.3 687.4,246.3C677.6,246.3 669.7,243.4 664,237.6C658.1,231.9 655.2,224 655.2,214M670.7,213.5C670.7,220.1 672.2,225.2 675.2,228.7C678.2,232.2 682.5,233.9 688.1,233.9C693.5,233.9 697.7,232.2 700.5,228.7C703.3,225.2 704.8,220 704.8,213.1C704.8,206.3 703.3,201.1 700.4,197.6C697.5,194.1 693.3,192.4 688,192.4C682.5,192.4 678.3,194.2 675.2,197.9C672.2,201.6 670.7,206.7 670.7,213.5" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M769.8,193.6L769.8,226.2C769.8,233 771.4,238 774.5,241.4C777.6,244.8 782.4,246.4 788.7,246.4C790.8,246.4 793,246.2 795.2,245.7C797.4,245.2 799,244.8 799.9,244.2L799.9,231.8C799,232.4 797.9,232.9 796.7,233.3C795.5,233.7 794.4,233.9 793.6,233.9C790.6,233.9 788.3,233.1 786.9,231.5C785.5,229.9 784.8,227.1 784.8,223.2L784.8,193.5L800,193.5L800,181.3L784.9,181.3L784.9,162.5L769.9,167.1L769.9,181.4L747.6,181.4L747.6,173.7C747.6,169.9 748.4,167 750.1,165C751.8,163 754.2,162.1 757.3,162.1C758.9,162.1 760.3,162.3 761.6,162.7C762.8,163.1 763.7,163.5 764.2,163.8L764.2,150.9C763.1,150.5 761.9,150.3 760.5,150.1C759.1,149.9 757.5,149.8 755.7,149.8C748.9,149.8 743.3,151.9 739,156.2C734.7,160.5 732.5,165.9 732.5,172.6L732.5,181.4L721.9,181.4L721.9,193.6L732.5,193.6L732.5,244.9L747.6,244.9L747.6,193.6L769.8,193.6Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M395.5,156.2L395.5,244.8L380.1,244.8L380.1,175.4L379.9,175.4L352.4,244.8L342.2,244.8L314,175.4L313.8,175.4L313.8,244.8L299.6,244.8L299.6,156.2L321.6,156.2L347.1,221.9L347.5,221.9L374.4,156.2L395.5,156.2Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M340,117.9C334.7,120.9 328.7,122.4 322,122.4C316.9,122.4 312.4,121.3 308.4,119C304.5,116.8 301.4,113.6 299.3,109.5C297.2,105.4 296.1,100.8 296.1,95.7C296.1,90.3 297.3,85.4 299.6,81.2C301.9,77 305.2,73.6 309.5,71.2C313.8,68.8 318.6,67.6 324,67.6C326.7,67.6 329.4,67.9 332.1,68.4C334.8,68.9 337,69.6 338.7,70.4L338.7,78.4C334.7,75.7 329.6,74.4 323.4,74.4C319.7,74.4 316.4,75.3 313.4,77.1C310.4,78.9 308.1,81.4 306.5,84.5C304.9,87.7 304.1,91.3 304.1,95.3C304.1,101.6 305.8,106.6 309.1,110.3C312.4,114 317,115.8 322.8,115.8C326.5,115.8 329.8,115.1 332.6,113.6L332.6,99.9L321.3,99.9L321.3,93.3L340,93.3L340,117.9Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M383.1,104.6L356.9,104.6C357,108.4 358.2,111.3 360.2,113.4C362.3,115.4 365,116.5 368.4,116.5C372.9,116.5 376.8,115.2 380.2,112.6L380.2,119C378.7,120 376.8,120.9 374.5,121.5C372.2,122.1 369.8,122.4 367.4,122.4C361.7,122.4 357.2,120.7 354.1,117.3C351,113.9 349.4,109.1 349.4,102.9C349.4,99.1 350.2,95.6 351.7,92.6C353.2,89.5 355.4,87.1 358.1,85.4C360.8,83.7 363.9,82.8 367.2,82.8C372.1,82.8 376,84.4 378.8,87.6C381.6,90.8 383,95.2 383,100.9L383,104.6L383.1,104.6ZM375.8,98.9C375.8,95.6 375,93.1 373.5,91.4C372,89.7 369.9,88.8 367.1,88.8C364.6,88.8 362.4,89.7 360.5,91.5C358.6,93.3 357.5,95.8 356.9,98.9L375.8,98.9Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M411.5,121.1C410.8,121.5 409.9,121.8 408.6,122C407.4,122.2 406.3,122.3 405.3,122.3C398.3,122.3 394.8,118.4 394.8,110.7L394.8,89.7L388.4,89.7L388.4,83.7L394.8,83.7L394.8,74.7L402.1,72.4L402.1,83.6L411.4,83.6L411.4,89.6L402.1,89.6L402.1,109.4C402.1,111.9 402.5,113.7 403.3,114.7C404.1,115.7 405.5,116.2 407.6,116.2C409,116.2 410.3,115.8 411.4,115L411.4,121.1L411.5,121.1Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M447.7,70.3C447.7,71.5 447.3,72.5 446.4,73.4C445.5,74.3 444.4,74.7 443.1,74.7C441.8,74.7 440.7,74.3 439.8,73.4C438.9,72.6 438.5,71.5 438.5,70.2C438.5,68.9 439,67.8 439.9,67C440.8,66.2 441.9,65.7 443.1,65.7C444.3,65.7 445.4,66.1 446.3,67C447.3,68 447.7,69 447.7,70.3M446.7,121.5L439.4,121.5L439.4,83.7L446.7,83.7L446.7,121.5Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M478.4,121.1C477.7,121.5 476.8,121.8 475.5,122C474.3,122.2 473.2,122.3 472.2,122.3C465.2,122.3 461.7,118.4 461.7,110.7L461.7,89.7L455.3,89.7L455.3,83.7L461.7,83.7L461.7,74.7L469,72.4L469,83.6L478.3,83.6L478.3,89.6L469,89.6L469,109.4C469,111.9 469.4,113.7 470.2,114.7C471,115.7 472.4,116.2 474.5,116.2C475.9,116.2 477.2,115.8 478.3,115L478.3,121.1L478.4,121.1Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M526.2,71.7C525,71.1 523.7,70.7 522.2,70.7C518.1,70.7 516.1,73.2 516.1,78.2L516.1,83.6L524.7,83.6L524.7,89.6L516.1,89.6L516.1,121.4L508.8,121.4L508.8,89.7L502.4,89.7L502.4,83.7L508.8,83.7L508.8,77.9C508.8,73.9 509.9,70.7 512.2,68.3C514.5,65.9 517.6,64.7 521.6,64.7C523.6,64.7 525.1,64.9 526.3,65.4L526.3,71.7L526.2,71.7Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M553.1,91C552.7,90.7 551.9,90.4 550.9,90.1C549.9,89.9 549,89.7 548.3,89.7C545.7,89.7 543.6,90.9 542,93.2C540.4,95.5 539.6,98.5 539.6,102.2L539.6,121.5L532.3,121.5L532.3,83.7L539.6,83.7L539.6,91.3L539.8,91.3C540.6,88.7 541.9,86.7 543.6,85.2C545.3,83.7 547.3,83 549.5,83C551,83 552.2,83.2 553,83.5L553,91L553.1,91Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M594.8,102.4C594.8,108.5 593,113.4 589.5,117C586,120.6 581.3,122.4 575.5,122.4C569.8,122.4 565.2,120.6 561.8,117.1C558.4,113.6 556.7,108.9 556.7,103C556.7,96.7 558.5,91.8 562,88.2C565.5,84.6 570.3,82.8 576.4,82.8C582.1,82.8 586.6,84.5 589.8,88C593.2,91.5 594.8,96.3 594.8,102.4M587.3,102.6C587.3,98.1 586.3,94.7 584.4,92.4C582.4,90.1 579.7,88.9 576.1,88.9C572.5,88.9 569.6,90.1 567.5,92.6C565.4,95 564.4,98.5 564.4,102.9C564.4,107.2 565.4,110.5 567.5,112.9C569.6,115.3 572.4,116.5 576.1,116.5C579.8,116.5 582.6,115.3 584.5,113C586.3,110.5 587.3,107.1 587.3,102.6" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M660.1,121.5L652.8,121.5L652.8,100C652.8,96.1 652.2,93.3 651,91.5C649.8,89.7 647.7,88.9 644.8,88.9C642.4,88.9 640.3,90 638.7,92.2C637,94.4 636.2,97.1 636.2,100.1L636.2,121.5L628.9,121.5L628.9,99.3C628.9,92.4 626.2,88.9 620.9,88.9C618.4,88.9 616.3,90 614.7,92.1C613.1,94.2 612.3,96.9 612.3,100.2L612.3,121.6L605,121.6L605,83.7L612.3,83.7L612.3,89.6L612.4,89.6C615.1,85 619.1,82.8 624.2,82.8C626.6,82.8 628.8,83.5 630.8,84.8C632.7,86.1 634.1,88 635,90.4C636.5,87.8 638.2,85.9 640.3,84.6C642.4,83.4 644.8,82.7 647.6,82.7C655.9,82.7 660,87.8 660,98.1L660,121.5L660.1,121.5Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 10 KiB |
46
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
groups:
|
||||
github-actions:
|
||||
patterns:
|
||||
- "*"
|
||||
|
||||
- package-ecosystem: "pub"
|
||||
directory: "/app"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
groups:
|
||||
pub:
|
||||
patterns:
|
||||
- "*"
|
||||
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/supabase/functions/_cmd"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
groups:
|
||||
docker:
|
||||
patterns:
|
||||
- "*"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/landing"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
groups:
|
||||
npm-landing:
|
||||
patterns:
|
||||
- "*"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/supabase/email-templates"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
groups:
|
||||
npm-email-templates:
|
||||
patterns:
|
||||
- "*"
|
||||
40
.github/workflows/continuous-delivery.yaml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -36,13 +36,13 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Setup QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Setup Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -50,7 +50,7 @@ jobs:
|
||||
|
||||
- name: Build and Push Docker Image
|
||||
id: docker_build
|
||||
uses: docker/build-push-action@v4
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
push: true
|
||||
context: ./supabase/functions
|
||||
@@ -69,7 +69,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -92,6 +92,8 @@ jobs:
|
||||
supabase functions deploy generate-magic-link-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
|
||||
supabase functions deploy image-proxy-v1 --no-verify-jwt --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
|
||||
supabase functions deploy profile-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
|
||||
supabase functions deploy profile-v2 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
|
||||
supabase functions deploy revenuecat-webhooks-v1 --no-verify-jwt --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
|
||||
supabase functions deploy stripe-create-billing-portal-link-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
|
||||
supabase functions deploy stripe-create-checkout-session-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
|
||||
supabase functions deploy stripe-webhooks-v1 --no-verify-jwt --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
|
||||
@@ -112,6 +114,8 @@ jobs:
|
||||
supabase functions deploy generate-magic-link-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
|
||||
supabase functions deploy image-proxy-v1 --no-verify-jwt --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
|
||||
supabase functions deploy profile-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
|
||||
supabase functions deploy profile-v2 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
|
||||
supabase functions deploy revenuecat-webhooks-v1 --no-verify-jwt --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
|
||||
supabase functions deploy stripe-create-billing-portal-link-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
|
||||
supabase functions deploy stripe-create-checkout-session-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
|
||||
supabase functions deploy stripe-webhooks-v1 --no-verify-jwt --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
|
||||
@@ -130,7 +134,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -162,7 +166,7 @@ jobs:
|
||||
- name: Setup Flutter
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
flutter-version: '3.7.12'
|
||||
flutter-version: '3.13.7'
|
||||
channel: 'stable'
|
||||
cache: true
|
||||
cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
|
||||
@@ -200,12 +204,12 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Flutter
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
flutter-version: '3.7.12'
|
||||
flutter-version: '3.13.7'
|
||||
channel: 'stable'
|
||||
cache: true
|
||||
cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
|
||||
@@ -218,7 +222,7 @@ jobs:
|
||||
- name: Build
|
||||
run: |
|
||||
flutter config --enable-macos-desktop
|
||||
flutter build macos --release --dart-define SUPABASE_URL=${{ secrets.SUPABASE_PROD_URL }} --dart-define SUPABASE_ANON_KEY=${{ secrets.SUPABASE_PROD_ANON_KEY }} --dart-define SUPABASE_SITE_URL=${{ secrets.SUPABASE_PROD_SITE_URL }} --dart-define GOOGLE_CLIENT_ID=${{ secrets.SUPABASE_PROD_GOOGLE_CLIENT_ID }}
|
||||
FLUTTER_XCODE_CODE_SIGN_IDENTITY="" FLUTTER_XCODE_CODE_SIGNING_REQUIRED=NO flutter build macos --release --dart-define SUPABASE_URL=${{ secrets.SUPABASE_PROD_URL }} --dart-define SUPABASE_ANON_KEY=${{ secrets.SUPABASE_PROD_ANON_KEY }} --dart-define SUPABASE_SITE_URL=${{ secrets.SUPABASE_PROD_SITE_URL }} --dart-define GOOGLE_CLIENT_ID=${{ secrets.SUPABASE_PROD_GOOGLE_CLIENT_ID }}
|
||||
|
||||
- name: Package
|
||||
run: |
|
||||
@@ -253,18 +257,21 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Packages
|
||||
run: |
|
||||
# Required for Flutter
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y ninja-build libgtk-3-dev
|
||||
# Required for Package "media_kit" which is used via "just_audio_media_kit" for Linux and Windows:
|
||||
# See: https://pub.dev/packages/media_kit and https://pub.dev/packages/just_audio_media_kit
|
||||
sudo apt-get install -y libmpv-dev mpv
|
||||
|
||||
- name: Setup Flutter
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
flutter-version: '3.7.12'
|
||||
flutter-version: '3.13.7'
|
||||
channel: 'stable'
|
||||
cache: true
|
||||
cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
|
||||
@@ -281,6 +288,9 @@ jobs:
|
||||
|
||||
- name: Package
|
||||
run: |
|
||||
cp linux/flatpak/app.feeddeck.feeddeck.desktop build/linux/x64/release/bundle/
|
||||
cp linux/flatpak/app.feeddeck.feeddeck.metainfo.xml build/linux/x64/release/bundle/
|
||||
cp linux/flatpak/app.feeddeck.feeddeck.svg build/linux/x64/release/bundle/
|
||||
cd build
|
||||
cp -r linux/x64/release/bundle/ feeddeck-linux-x86_64
|
||||
tar -czf feeddeck-linux-x86_64.tar.gz feeddeck-linux-x86_64
|
||||
@@ -314,12 +324,12 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Flutter
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
flutter-version: '3.7.12'
|
||||
flutter-version: '3.13.7'
|
||||
channel: 'stable'
|
||||
cache: true
|
||||
cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
|
||||
|
||||
2
.github/workflows/release.yaml
vendored
@@ -37,7 +37,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v3
|
||||
|
||||
@@ -57,10 +57,10 @@ check your installed version:
|
||||
```sh
|
||||
$ flutter --version
|
||||
|
||||
Flutter 3.7.12 • channel stable • https://github.com/flutter/flutter.git
|
||||
Framework • revision 4d9e56e694 (8 weeks ago) • 2023-04-17 21:47:46 -0400
|
||||
Engine • revision 1a65d409c7
|
||||
Tools • Dart 2.19.6 • DevTools 2.20.1
|
||||
Flutter 3.13.7 • channel stable • https://github.com/flutter/flutter.git
|
||||
Framework • revision 2f708eb839 (4 days ago) • 2023-10-09 09:58:08 -0500
|
||||
Engine • revision a794cf2681
|
||||
Tools • Dart 3.1.3 • DevTools 2.25.0
|
||||
|
||||
|
||||
$ deno --version
|
||||
@@ -90,9 +90,10 @@ provide the following arguments: `--dart-define SUPABASE_URL=<SUPABASE_URL>`,
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "FeedDeck (Chrome)",
|
||||
"request": "launch",
|
||||
"name": "Local - Chrome",
|
||||
"type": "dart",
|
||||
"request": "launch",
|
||||
"program": "app/lib/main.dart",
|
||||
"args": [
|
||||
"-d",
|
||||
"chrome",
|
||||
@@ -110,28 +111,10 @@ provide the following arguments: `--dart-define SUPABASE_URL=<SUPABASE_URL>`,
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "FeedDeck (Web Server)",
|
||||
"request": "launch",
|
||||
"name": "Local - iOS Simulator",
|
||||
"type": "dart",
|
||||
"args": [
|
||||
"-d",
|
||||
"web-server",
|
||||
"--web-port",
|
||||
"3000",
|
||||
"--dart-define",
|
||||
"SUPABASE_URL=<SUPABASE_URL>",
|
||||
"--dart-define",
|
||||
"SUPABASE_ANON_KEY=<SUPABASE_ANON_KEY>",
|
||||
"--dart-define",
|
||||
"SUPABASE_SITE_URL=<SUPABASE_SITE_URL>",
|
||||
"--dart-define",
|
||||
"GOOGLE_CLIENT_ID=<GOOGLE_CLIENT_ID>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "FeedDeck (iOS)",
|
||||
"request": "launch",
|
||||
"type": "dart",
|
||||
"program": "app/lib/main.dart",
|
||||
"args": [
|
||||
"-d",
|
||||
"iPhone 14 Pro Max",
|
||||
@@ -146,9 +129,10 @@ provide the following arguments: `--dart-define SUPABASE_URL=<SUPABASE_URL>`,
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "FeedDeck (macOS)",
|
||||
"request": "launch",
|
||||
"name": "Local - macOS",
|
||||
"type": "dart",
|
||||
"request": "launch",
|
||||
"program": "app/lib/main.dart",
|
||||
"args": [
|
||||
"-d",
|
||||
"macOS",
|
||||
@@ -326,6 +310,8 @@ supabase functions deploy delete-user-v1 --project-ref <PROJECT-ID> --import-map
|
||||
supabase functions deploy generate-magic-link-v1 --project-ref <PROJECT-ID> --import-map supabase/functions/import_map.json
|
||||
supabase functions deploy image-proxy-v1 --no-verify-jwt --project-ref <PROJECT-ID> --import-map supabase/functions/import_map.json
|
||||
supabase functions deploy profile-v1 --project-ref <PROJECT-ID> --import-map supabase/functions/import_map.json
|
||||
supabase functions deploy profile-v2 --project-ref <PROJECT-ID> --import-map supabase/functions/import_map.json
|
||||
supabase functions deploy revenuecat-webhooks-v1 --no-verify-jwt --project-ref <PROJECT-ID> --import-map supabase/functions/import_map.json
|
||||
supabase functions deploy stripe-create-billing-portal-link-v1 --project-ref <PROJECT-ID> --import-map supabase/functions/import_map.json
|
||||
supabase functions deploy stripe-create-checkout-session-v1 --project-ref <PROJECT-ID> --import-map supabase/functions/import_map.json
|
||||
supabase functions deploy stripe-webhooks-v1 --no-verify-jwt --project-ref <PROJECT-ID> --import-map supabase/functions/import_map.json
|
||||
@@ -411,26 +397,45 @@ Android, macOS, Windows and Linux if you do not want to use the official ones.
|
||||
2. Update the `version` key and the `msix_config.msix_version` key in the
|
||||
`pubspec.yaml` file.
|
||||
|
||||
3. Delete the `build/` and `.dart_tool/` directories via the `flutter clean`
|
||||
3. Add the new release to the `releases` section in
|
||||
[`app.feeddeck.feeddeck.metainfo.xml`](app/linux/flatpak/app.feeddeck.feeddeck.metainfo.xml).
|
||||
|
||||
4. Delete the `build/` and `.dart_tool/` directories via the `flutter clean`
|
||||
command.
|
||||
|
||||
4. Build the app for Web by running `flutter build web`. The build can be found
|
||||
5. Build the app for Web by running `flutter build web`. The build can be found
|
||||
at `app/build/web` and must be uploaded to your hosting provider.
|
||||
|
||||
5. Build the app for Linux by running `flutter build linux --release`.
|
||||
6. Build the app for Linux by running `flutter build linux --release`. To build
|
||||
the `arm64` version the following commands can be run on a Raspberry Pi. Once
|
||||
the `feeddeck-linux-arm64.tar.gz` archive was created it can be uploaded to
|
||||
the GitHub release.
|
||||
|
||||
6. Build the app for macOS by running `flutter build macos --release`. Open
|
||||
```sh
|
||||
cp linux/flatpak/app.feeddeck.feeddeck.desktop build/linux/arm64/release/bundle/
|
||||
cp linux/flatpak/app.feeddeck.feeddeck.metainfo.xml build/linux/arm64/release/bundle/
|
||||
cp linux/flatpak/app.feeddeck.feeddeck.svg build/linux/arm64/release/bundle/
|
||||
cd build
|
||||
cp -r linux/arm64/release/bundle/ feeddeck-linux-arm64
|
||||
tar -czf feeddeck-linux-arm64.tar.gz feeddeck-linux-arm64
|
||||
```
|
||||
|
||||
Update the `app.feeddeck.feeddeck.yml` file at
|
||||
[github.com/flathub/app.feeddeck.feeddeck](https://github.com/flathub/app.feeddeck.feeddeck)
|
||||
with the new release.
|
||||
|
||||
7. Build the app for macOS by running `flutter build macos --release`. Open
|
||||
Xcode and select **Product** > **Archive** to create and open the archive.
|
||||
After that the **Validate App** and **Distribute App** options can be used to
|
||||
upload the build to
|
||||
[https://appstoreconnect.apple.com](https://appstoreconnect.apple.com).
|
||||
|
||||
7. Build the app for Windows by running `flutter build windows --release`. and
|
||||
8. Build the app for Windows by running `flutter build windows --release`. and
|
||||
`flutter pub run msix:create --output-path build --output-name feeddeck`. The
|
||||
build can be found at `app/build/feeddeck.msix` and must be uploaded to
|
||||
[https://partner.microsoft.com/en-us/dashboard/products/9NPHPGRRCT5H/overview](https://partner.microsoft.com/en-us/dashboard/products/9NPHPGRRCT5H/overview).
|
||||
|
||||
8. Create a file `app/android/key.properties` with the following content:
|
||||
9. Create a file `app/android/key.properties` with the following content:
|
||||
|
||||
```plain
|
||||
storePassword=
|
||||
@@ -439,12 +444,12 @@ Android, macOS, Windows and Linux if you do not want to use the official ones.
|
||||
storeFile=
|
||||
```
|
||||
|
||||
9. Build the app for Android by running `flutter build appbundle`. The build can
|
||||
be found at `app/build/app/outputs/bundle/release/app-release.aab` and must
|
||||
be uploaded to
|
||||
[https://play.google.com/apps/publish](https://play.google.com/apps/publish).
|
||||
10. Build the app for Android by running `flutter build appbundle`. The build
|
||||
can be found at `app/build/app/outputs/bundle/release/app-release.aab` and
|
||||
must be uploaded to
|
||||
[https://play.google.com/apps/publish](https://play.google.com/apps/publish).
|
||||
|
||||
10. Build the app for iOS by running `flutter build ipa`. The build can be found
|
||||
11. Build the app for iOS by running `flutter build ipa`. The build can be found
|
||||
at `app/build/ios/archive/Runner.xcarchive` and must be opened in Xcode. In
|
||||
Xcode the **Validate App** and **Distribute App** options can be used to
|
||||
upload the build to
|
||||
|
||||
@@ -7,9 +7,12 @@ TweetDeck. FeedDeck allows you to follow your favorite feeds in one place on all
|
||||
platforms.
|
||||
|
||||
<p>
|
||||
<a href="https://feeddeck.app/download" target="_blank"><img src=".github/assets/badge-app-store.png" height="50"></a>
|
||||
<a href="https://feeddeck.app/download" target="_blank"><img src=".github/assets/badge-google-play.png" height="50"></a>
|
||||
<a href="https://feeddeck.app/download" target="_self"><img src=".github/assets/badge-desktop.png" height="50"></a>
|
||||
<a href="https://apps.apple.com/us/app/feeddeck/id6451055362" target="_blank"><img src=".github/assets/badge-app-store.svg" height="50"></a>
|
||||
<a href="https://play.google.com/store/apps/details?id=app.feeddeck.feeddeck" target="_blank"><img src=".github/assets/badge-google-play.svg" height="50"></a>
|
||||
<a href="https://app.feeddeck.app" target="_blank"><img src=".github/assets/badge-web.svg" height="50"></a>
|
||||
<a href="https://apps.apple.com/us/app/feeddeck/id6451055362" target="_blank"><img src=".github/assets/badge-mac-app-store.svg" height="50"></a>
|
||||
<a href="https://www.microsoft.com/store/apps/9NPHPGRRCT5H" target="_blank"><img src=".github/assets/badge-windows-store.svg" height="50"></a>
|
||||
<a href="https://flathub.org/en/apps/app.feeddeck.feeddeck" target="_blank"><img src=".github/assets/badge-flathub.svg" height="50"></a>
|
||||
</p>
|
||||
|
||||
<img src=".github/assets/screenshot.png" width="100%" />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="app.feeddeck.feeddeck">
|
||||
<application
|
||||
android:label="feeddeck"
|
||||
android:label="FeedDeck"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:usesCleartextTraffic="true"
|
||||
|
||||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
@@ -26,6 +26,6 @@ subprojects {
|
||||
project.evaluationDependsOn(':app')
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
tasks.register("clean", Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Uncomment this line to define a global platform for your project
|
||||
# platform :ios, '11.0'
|
||||
platform :ios, '11.0'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
||||
@@ -13,17 +13,25 @@ PODS:
|
||||
- FMDB/standard (2.7.5)
|
||||
- just_audio (0.0.1):
|
||||
- Flutter
|
||||
- media_kit_native_event_loop (1.0.0):
|
||||
- Flutter
|
||||
- package_info_plus (0.4.5):
|
||||
- Flutter
|
||||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- purchases_flutter (6.0.0):
|
||||
- Flutter
|
||||
- PurchasesHybridCommon (= 7.0.0)
|
||||
- PurchasesHybridCommon (7.0.0):
|
||||
- RevenueCat (= 4.27.0)
|
||||
- RevenueCat (4.27.0)
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- sign_in_with_apple (0.0.1):
|
||||
- Flutter
|
||||
- sqflite (0.0.2):
|
||||
- sqflite (0.0.3):
|
||||
- Flutter
|
||||
- FMDB (>= 2.7.5)
|
||||
- url_launcher_ios (0.0.1):
|
||||
@@ -38,9 +46,11 @@ DEPENDENCIES:
|
||||
- Flutter (from `Flutter`)
|
||||
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
||||
- just_audio (from `.symlinks/plugins/just_audio/ios`)
|
||||
- media_kit_native_event_loop (from `.symlinks/plugins/media_kit_native_event_loop/ios`)
|
||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`)
|
||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/ios`)
|
||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- purchases_flutter (from `.symlinks/plugins/purchases_flutter/ios`)
|
||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- sign_in_with_apple (from `.symlinks/plugins/sign_in_with_apple/ios`)
|
||||
- sqflite (from `.symlinks/plugins/sqflite/ios`)
|
||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||
@@ -49,6 +59,8 @@ DEPENDENCIES:
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- FMDB
|
||||
- PurchasesHybridCommon
|
||||
- RevenueCat
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
app_links:
|
||||
@@ -63,12 +75,16 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
||||
just_audio:
|
||||
:path: ".symlinks/plugins/just_audio/ios"
|
||||
media_kit_native_event_loop:
|
||||
:path: ".symlinks/plugins/media_kit_native_event_loop/ios"
|
||||
package_info_plus:
|
||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||
path_provider_foundation:
|
||||
:path: ".symlinks/plugins/path_provider_foundation/ios"
|
||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||
purchases_flutter:
|
||||
:path: ".symlinks/plugins/purchases_flutter/ios"
|
||||
shared_preferences_foundation:
|
||||
:path: ".symlinks/plugins/shared_preferences_foundation/ios"
|
||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||
sign_in_with_apple:
|
||||
:path: ".symlinks/plugins/sign_in_with_apple/ios"
|
||||
sqflite:
|
||||
@@ -86,14 +102,18 @@ SPEC CHECKSUMS:
|
||||
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
|
||||
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
||||
just_audio: baa7252489dbcf47a4c7cc9ca663e9661c99aafa
|
||||
media_kit_native_event_loop: f1ee9f941ec0af371b245969a3e010901c375480
|
||||
package_info_plus: fd030dabf36271f146f1f3beacd48f564b0f17f7
|
||||
path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9
|
||||
shared_preferences_foundation: 986fc17f3d3251412d18b0265f9c64113a8c2472
|
||||
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
|
||||
purchases_flutter: 549ccfbbaf5e7cd195043c714b69a35e278c00f1
|
||||
PurchasesHybridCommon: af3b2413f9cb999bc1fdca44770bdaf39dfb89fa
|
||||
RevenueCat: 84fbe2eb9bbf63e1abf346ccd3ff9ee45d633e3b
|
||||
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
|
||||
sign_in_with_apple: f3bf75217ea4c2c8b91823f225d70230119b8440
|
||||
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
|
||||
sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a
|
||||
url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4
|
||||
webview_flutter_wkwebview: 2e2d318f21a5e036e2c3f26171342e95908bd60a
|
||||
|
||||
PODFILE CHECKSUM: 92152382e3e2d8bbf76cfce953216c7c829d94ce
|
||||
PODFILE CHECKSUM: ec83c31511fbc978a9918c6fda235238118483f5
|
||||
|
||||
COCOAPODS: 1.12.1
|
||||
COCOAPODS: 1.13.0
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
11A5CB70E48EE53811F041B1 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E4F63A76E5CF724D941DA24D /* Pods_Runner.framework */; };
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||
55F35B592ABF74D1007331B3 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 55F35B582ABF74D1007331B3 /* StoreKit.framework */; };
|
||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||
@@ -34,6 +35,7 @@
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||
551175C42A39020E00A80299 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
||||
55F35B582ABF74D1007331B3 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
|
||||
5C1B3914BEEA60B960FC050D /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
@@ -56,6 +58,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
11A5CB70E48EE53811F041B1 /* Pods_Runner.framework in Frameworks */,
|
||||
55F35B592ABF74D1007331B3 /* StoreKit.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -121,6 +124,7 @@
|
||||
AC99711BA86FAD05300ADB7E /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
55F35B582ABF74D1007331B3 /* StoreKit.framework */,
|
||||
E4F63A76E5CF724D941DA24D /* Pods_Runner.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
@@ -157,7 +161,7 @@
|
||||
97C146E61CF9000F007C117D /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1300;
|
||||
LastUpgradeCheck = 1430;
|
||||
ORGANIZATIONNAME = "";
|
||||
TargetAttributes = {
|
||||
97C146ED1CF9000F007C117D = {
|
||||
@@ -228,6 +232,7 @@
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
|
||||
);
|
||||
name = "Thin Binary";
|
||||
outputPaths = (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1300"
|
||||
LastUpgradeVersion = "1430"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
||||
@@ -1,73 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>FeedDeck</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>feeddeck</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>UIStatusBarHidden</key>
|
||||
<true/>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>app.feeddeck.feeddeck</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>FeedDeck</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>feeddeck</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>app.feeddeck.feeddeck</string>
|
||||
</array>
|
||||
</dict>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>audio</string>
|
||||
</array>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>audio</string>
|
||||
</array>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIStatusBarHidden</key>
|
||||
<false/>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:io' show Platform;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
||||
@@ -65,6 +66,23 @@ void main() async {
|
||||
runApp(const FeedDeckApp());
|
||||
}
|
||||
|
||||
/// [FeedDeckScrollBehavior] changes the scrolling behavior of the app. This is
|
||||
/// required to enable scrolling on desktop via drag, which is the only way that
|
||||
/// a user can scroll vertically with a mouse via drag.
|
||||
///
|
||||
/// E.g. this is required for the [ColumnLayoutSources] widget, where we rely on
|
||||
/// the drag gesture to scroll the list of sources.
|
||||
class FeedDeckScrollBehavior extends MaterialScrollBehavior {
|
||||
@override
|
||||
Set<PointerDeviceKind> get dragDevices => {
|
||||
PointerDeviceKind.touch,
|
||||
PointerDeviceKind.mouse,
|
||||
PointerDeviceKind.trackpad,
|
||||
PointerDeviceKind.stylus,
|
||||
PointerDeviceKind.unknown,
|
||||
};
|
||||
}
|
||||
|
||||
/// [onGenerateRoute] is used in `onGenerateRoute` and `onGenerateInitialRoutes`
|
||||
/// of the [MaterialApp] to add handling for some special routes were do not
|
||||
/// want to render the [Home] widget (e.g. set a new password).
|
||||
@@ -131,6 +149,7 @@ class FeedDeckApp extends StatelessWidget {
|
||||
),
|
||||
canvasColor: Constants.canvasColor,
|
||||
appBarTheme: const AppBarTheme(
|
||||
centerTitle: true,
|
||||
backgroundColor: Constants.appBarBackgroundColor,
|
||||
scrolledUnderElevation: Constants.scrolledUnderElevation,
|
||||
elevation: Constants.appBarElevation,
|
||||
@@ -173,6 +192,7 @@ class FeedDeckApp extends StatelessWidget {
|
||||
},
|
||||
),
|
||||
),
|
||||
scrollBehavior: FeedDeckScrollBehavior(),
|
||||
onGenerateInitialRoutes: (initialRoute) =>
|
||||
[onGenerateRoute(RouteSettings(name: initialRoute))],
|
||||
onGenerateRoute: (RouteSettings settings) =>
|
||||
|
||||
@@ -29,6 +29,40 @@ FDProfileTier getProfileTierFromString(String state) {
|
||||
return FDProfileTier.free;
|
||||
}
|
||||
|
||||
/// [FDProfileSubscriptionProvider] is a enum value which defines the different
|
||||
/// subscription providers for a profile. A user can use [stripe] or
|
||||
/// [revenuecat] to get a premium account.
|
||||
enum FDProfileSubscriptionProvider {
|
||||
stripe,
|
||||
revenuecat,
|
||||
}
|
||||
|
||||
/// [FDProfileSubscriptionProviderExtension] defines all extensions which are
|
||||
/// available for the [FDProfileSubscriptionProvider] enum type.
|
||||
extension FDProfileSubscriptionProviderExtension
|
||||
on FDProfileSubscriptionProvider {
|
||||
/// [toShortString] returns a short string of the source type which can safely
|
||||
/// be passed to our database.
|
||||
String toShortString() {
|
||||
return toString().split('.').last;
|
||||
}
|
||||
}
|
||||
|
||||
/// [getSourceTypeFromString] returns the [FDProfileSubscriptionProvider] from
|
||||
/// his string representation. This is used to parse the JSON value returned by
|
||||
/// our database into correct enum value in the [FDSource] model.
|
||||
FDProfileSubscriptionProvider? getProfileSubscriptionProviderFromString(
|
||||
String state,
|
||||
) {
|
||||
for (FDProfileSubscriptionProvider element
|
||||
in FDProfileSubscriptionProvider.values) {
|
||||
if (element.toShortString() == state) {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// [FDProfile] is the model for a profile of a user in our app. The following
|
||||
/// fields are required for a profile:
|
||||
/// - An [id] to uniquely identify a column in the database
|
||||
@@ -38,6 +72,7 @@ FDProfileTier getProfileTierFromString(String state) {
|
||||
class FDProfile {
|
||||
String id;
|
||||
FDProfileTier tier;
|
||||
FDProfileSubscriptionProvider? subscriptionProvider;
|
||||
bool accountGithub;
|
||||
int createdAt;
|
||||
int updatedAt;
|
||||
@@ -45,6 +80,7 @@ class FDProfile {
|
||||
FDProfile({
|
||||
required this.id,
|
||||
required this.tier,
|
||||
required this.subscriptionProvider,
|
||||
required this.accountGithub,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
@@ -54,6 +90,12 @@ class FDProfile {
|
||||
return FDProfile(
|
||||
id: data['id'],
|
||||
tier: getProfileTierFromString(data['tier']),
|
||||
subscriptionProvider: data.containsKey('subscriptionProvider') &&
|
||||
data['subscriptionProvider'] != null
|
||||
? getProfileSubscriptionProviderFromString(
|
||||
data['subscriptionProvider'],
|
||||
)
|
||||
: null,
|
||||
accountGithub: data['accountGithub'],
|
||||
createdAt: data['createdAt'],
|
||||
updatedAt: data['updatedAt'],
|
||||
|
||||
@@ -152,7 +152,7 @@ class AppRepository with ChangeNotifier {
|
||||
.from('decks')
|
||||
.insert({
|
||||
'name': name,
|
||||
'userId': Supabase.instance.client.auth.currentUser!.id
|
||||
'userId': Supabase.instance.client.auth.currentUser!.id,
|
||||
})
|
||||
.select()
|
||||
.single();
|
||||
|
||||
@@ -105,9 +105,9 @@ class ItemsRepository with ChangeNotifier {
|
||||
Future<void> _init() async {
|
||||
final state = ItemsRepositoryStore().get(column.identifier());
|
||||
if (state != null) {
|
||||
_status = ItemsStatus.loaded;
|
||||
_items.addAll(state.items);
|
||||
_status = state.status;
|
||||
_filters = state.filters;
|
||||
_items.addAll(state.items);
|
||||
notifyListeners();
|
||||
} else {
|
||||
await _getItems();
|
||||
@@ -168,7 +168,7 @@ class ItemsRepository with ChangeNotifier {
|
||||
/// filter to page through all the items.
|
||||
final data = await filter
|
||||
.order('publishedAt')
|
||||
.range(_filters.offsetFilter, _filters.offsetFilter + 50);
|
||||
.range(_filters.offsetFilter, _filters.offsetFilter + 50 - 1);
|
||||
|
||||
/// The returned items are added to the [_items] field and the status is
|
||||
/// set to [ItemsStatus.loaded] or [ItemsStatus.loadedLast] based on the
|
||||
@@ -189,7 +189,12 @@ class ItemsRepository with ChangeNotifier {
|
||||
/// Finally we store the state of the repository, so that we do not have
|
||||
/// to retrieve the items from the database again when therepository is
|
||||
/// reinitialized.
|
||||
ItemsRepositoryStore().set(column.identifier(), _items, _filters);
|
||||
ItemsRepositoryStore().set(
|
||||
column.identifier(),
|
||||
_status,
|
||||
_filters,
|
||||
_items,
|
||||
);
|
||||
notifyListeners();
|
||||
} catch (_) {
|
||||
_status = ItemsStatus.loaded;
|
||||
@@ -278,7 +283,7 @@ class ItemsRepository with ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
ItemsRepositoryStore().set(column.id, _items, _filters);
|
||||
ItemsRepositoryStore().set(column.id, _status, _filters, _items);
|
||||
notifyListeners();
|
||||
} catch (err) {
|
||||
rethrow;
|
||||
@@ -288,18 +293,27 @@ class ItemsRepository with ChangeNotifier {
|
||||
/// [updateReadStates] can be used to mark a list of items provided via their
|
||||
/// [itemIds] as read / unread. When the [read] value is `true` items are
|
||||
/// marked as read and when it is `false` as unread.
|
||||
///
|
||||
/// We have to split the provided list of [itemIds] into chunks of 25 items,
|
||||
/// to avoid the request uri to long error from Supabase. We decided to use 25
|
||||
/// items per chunk, because we think that this is a good tradeoff between the
|
||||
/// number of requests and the number of items we can update at once.
|
||||
Future<void> updateReadStates(List<String> itemIds, bool read) async {
|
||||
try {
|
||||
await Supabase.instance.client
|
||||
.from('items')
|
||||
.update({'isRead': read}).in_('id', itemIds);
|
||||
for (var i = 0; i < _items.length; i++) {
|
||||
if (itemIds.contains(_items[i].id)) {
|
||||
_items[i].isRead = read;
|
||||
final chunks = itemIds.slices(25).toList();
|
||||
|
||||
for (var i = 0; i < chunks.length; i++) {
|
||||
await Supabase.instance.client
|
||||
.from('items')
|
||||
.update({'isRead': read}).in_('id', chunks[i]);
|
||||
for (var j = 0; j < _items.length; j++) {
|
||||
if (chunks[i].contains(_items[j].id)) {
|
||||
_items[j].isRead = read;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ItemsRepositoryStore().set(column.id, _items, _filters);
|
||||
ItemsRepositoryStore().set(column.id, _status, _filters, _items);
|
||||
notifyListeners();
|
||||
} catch (err) {
|
||||
rethrow;
|
||||
@@ -321,7 +335,7 @@ class ItemsRepository with ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
ItemsRepositoryStore().set(column.id, _items, _filters);
|
||||
ItemsRepositoryStore().set(column.id, _status, _filters, _items);
|
||||
notifyListeners();
|
||||
} catch (err) {
|
||||
rethrow;
|
||||
@@ -333,12 +347,14 @@ class ItemsRepository with ChangeNotifier {
|
||||
/// in the [ItemsRepositoryStore]. The state contains all the loaded [items] and
|
||||
/// the [filters] set by user to load the items.
|
||||
class ItemsRepositoryStoreState {
|
||||
List<FDItem> items;
|
||||
ItemsStatus status;
|
||||
ItemsFilters filters;
|
||||
List<FDItem> items;
|
||||
|
||||
ItemsRepositoryStoreState({
|
||||
required this.items,
|
||||
required this.status,
|
||||
required this.filters,
|
||||
required this.items,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -353,7 +369,7 @@ class ItemsRepositoryStore {
|
||||
static final ItemsRepositoryStore _instance =
|
||||
ItemsRepositoryStore._internal();
|
||||
|
||||
final Map<String, ItemsRepositoryStoreState> itemsRepositoryStoreStates = {};
|
||||
final Map<String, ItemsRepositoryStoreState> _itemsRepositoryStoreStates = {};
|
||||
|
||||
factory ItemsRepositoryStore() {
|
||||
return _instance;
|
||||
@@ -366,7 +382,7 @@ class ItemsRepositoryStore {
|
||||
/// returns `null` to indicate that we have to get the items from the
|
||||
/// database.
|
||||
ItemsRepositoryStoreState? get(String columnId) {
|
||||
return itemsRepositoryStoreStates[columnId];
|
||||
return _itemsRepositoryStoreStates[columnId];
|
||||
}
|
||||
|
||||
/// [set] saves the [items] and [filters] for a [columnId] in the store. This
|
||||
@@ -375,10 +391,23 @@ class ItemsRepositoryStore {
|
||||
///
|
||||
/// The best is to call the [set] function right before we call
|
||||
/// `notifyListeners` in the repository.
|
||||
set(String columnId, List<FDItem> items, ItemsFilters filters) {
|
||||
return itemsRepositoryStoreStates[columnId] = ItemsRepositoryStoreState(
|
||||
items: items,
|
||||
set(
|
||||
String columnId,
|
||||
ItemsStatus status,
|
||||
ItemsFilters filters,
|
||||
List<FDItem> items,
|
||||
) {
|
||||
return _itemsRepositoryStoreStates[columnId] = ItemsRepositoryStoreState(
|
||||
status: status,
|
||||
filters: filters,
|
||||
items: items,
|
||||
);
|
||||
}
|
||||
|
||||
/// [clear] deletes all the stored [_itemsRepositoryStoreStates] from the
|
||||
/// store. This method can be used to clear the cache, e.g. when a user
|
||||
/// changes the active deck or signes out.
|
||||
clear() {
|
||||
_itemsRepositoryStoreStates.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||
|
||||
import 'package:feeddeck/models/profile.dart';
|
||||
import 'package:feeddeck/models/source.dart';
|
||||
import 'package:feeddeck/utils/api_exception.dart';
|
||||
|
||||
enum FDProfileStatus {
|
||||
@@ -13,14 +12,21 @@ enum FDProfileStatus {
|
||||
initialized,
|
||||
}
|
||||
|
||||
/// The [ProfileRepository] is used to fetch and update a users profile data.
|
||||
/// The users profile contains all the required information for the users
|
||||
/// subscription status and the users connected accounts.
|
||||
class ProfileRepository with ChangeNotifier {
|
||||
FDProfileStatus _status = FDProfileStatus.uninitialized;
|
||||
FDProfile? _profile;
|
||||
|
||||
FDProfileStatus get status => _status;
|
||||
FDProfileTier get tier => _profile?.tier ?? FDProfileTier.free;
|
||||
FDProfileSubscriptionProvider? get subscriptionProvider =>
|
||||
_profile?.subscriptionProvider;
|
||||
bool get accountGithub => _profile?.accountGithub ?? false;
|
||||
|
||||
/// [init] is used to fetch the users profile from the `profile-v2` edge
|
||||
/// function.
|
||||
Future<void> init(bool force) async {
|
||||
if (_status == FDProfileStatus.initialized && force == false) {
|
||||
return;
|
||||
@@ -28,7 +34,7 @@ class ProfileRepository with ChangeNotifier {
|
||||
|
||||
try {
|
||||
final result = await Supabase.instance.client.functions.invoke(
|
||||
'profile-v1',
|
||||
'profile-v2/getProfile',
|
||||
method: HttpMethod.get,
|
||||
);
|
||||
|
||||
@@ -45,16 +51,25 @@ class ProfileRepository with ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> addGithubAccount(String token) async {
|
||||
/// [setTier] is used to update the users tier. We do not have to make an API
|
||||
/// call to update the tier in the database, because this is done via Webhooks
|
||||
/// by the connected payment provider.
|
||||
///
|
||||
/// This is only required to reflect the update in the Flutter app.
|
||||
void setTier(FDProfileTier tier) {
|
||||
_profile?.tier = tier;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// [githubAddAccount] is used to add a GitHub account to the users profile.
|
||||
/// For this the user must provide an private access token with the required
|
||||
/// scopes.
|
||||
Future<void> githubAddAccount(String token) async {
|
||||
final result = await Supabase.instance.client.functions.invoke(
|
||||
'profile-v1',
|
||||
'profile-v2/githubAddAccount',
|
||||
method: HttpMethod.post,
|
||||
body: {
|
||||
'action': 'add-account',
|
||||
'sourceType': FDSourceType.github.toShortString(),
|
||||
'options': {
|
||||
'token': token,
|
||||
}
|
||||
'token': token,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -66,14 +81,12 @@ class ProfileRepository with ChangeNotifier {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> deleteGithubAccount() async {
|
||||
/// [githubDeleteAccount] deletes the users connected GitHub account. For that
|
||||
/// we delete the GitHub access token from the database.
|
||||
Future<void> githubDeleteAccount() async {
|
||||
final result = await Supabase.instance.client.functions.invoke(
|
||||
'profile-v1',
|
||||
method: HttpMethod.post,
|
||||
body: {
|
||||
'action': 'delete-account',
|
||||
'sourceType': FDSourceType.github.toShortString(),
|
||||
},
|
||||
'profile-v2/githubDeleteAccount',
|
||||
method: HttpMethod.delete,
|
||||
);
|
||||
|
||||
if (result.status != 200) {
|
||||
|
||||
@@ -17,7 +17,19 @@ class SettingsRepository {
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Iml0eWp1Y3BzcmFzYXZyaWVwc2NyIiwicm9sZSI6ImFub24iLCJpYXQiOjE2OTQwMjY0NjIsImV4cCI6MjAwOTYwMjQ2Mn0.IDo7j9Kh8-5kHLtrZtHTvLf8lUkj7jiLynpIXSZbRFs';
|
||||
String supabaseSiteUrl = 'https://app.feeddeck.app';
|
||||
String googleClientId =
|
||||
'420185423235-9ehth1eodl4lt3cdns7kaf2e89eo6rkq.apps.googleusercontent.com';
|
||||
'296452997087-2o1qasg1gdbe39b1l39dds1doq3t6h2e.apps.googleusercontent.com';
|
||||
|
||||
/// By default the [subscriptionEnabled] variable is set to `true`, so that a
|
||||
/// user can subscribe to FeedDeck Premium. If the variable is set to `false`
|
||||
/// the user can not subscribe to FeedDeck Premium.
|
||||
bool subscriptionEnabled = true;
|
||||
|
||||
/// The [revenueCatAppStoreKey] and [revenueCatGooglePlayKey] are used for the
|
||||
/// in-app purchases. The [revenueCatAppStoreKey] is used for the Apple App
|
||||
/// Store on iOS and macOS. The [revenueCatGooglePlayKey] is used for the
|
||||
/// Google Play Store on Android.
|
||||
final String revenueCatAppStoreKey = 'appl_kThbIaMkylDBtCEmsfczvgCBram';
|
||||
final String revenueCatGooglePlayKey = 'goog_tBFPbLbygjioviXRIlGlmUOKZYA';
|
||||
|
||||
factory SettingsRepository() {
|
||||
return _instance;
|
||||
@@ -52,11 +64,16 @@ class SettingsRepository {
|
||||
googleClientIdPrefs != null) {
|
||||
/// Store the user provided values within the [SettingsRepository] and
|
||||
/// use them to initialize the Supabase client.
|
||||
///
|
||||
/// Also set the [subscriptionEnabled] variabel to `false`, so that the
|
||||
/// user can not subscribe to FeedDeck Premium.
|
||||
supabaseUrl = supabaseUrlPrefs;
|
||||
supabaseAnonKey = supabaseAnonKeyPrefs;
|
||||
supabaseSiteUrl = supabaseSiteUrlPrefs;
|
||||
googleClientId = googleClientIdPrefs;
|
||||
|
||||
subscriptionEnabled = false;
|
||||
|
||||
await Supabase.initialize(
|
||||
url: supabaseUrlPrefs,
|
||||
anonKey: supabaseAnonKeyPrefs,
|
||||
|
||||
@@ -121,7 +121,7 @@ class _ColumnLayoutHeaderState extends State<ColumnLayoutHeader> {
|
||||
),
|
||||
Text(
|
||||
Characters(
|
||||
'${items.column.sources.length} ${items.column.sources.length == 1 ? 'Source' : 'Sources'} / ${items.items.length} ${items.items.length == 1 ? 'Item' : 'Items'}',
|
||||
'${items.column.sources.length} ${items.column.sources.length == 1 ? 'Source' : 'Sources'} / ${items.items.length}${items.status == ItemsStatus.loaded ? '+' : ''} ${items.items.length == 1 ? 'Item' : 'Items'}',
|
||||
)
|
||||
.replaceAll(
|
||||
Characters(''),
|
||||
|
||||
@@ -100,7 +100,7 @@ class ColumnLayoutHeaderSettings extends StatelessWidget {
|
||||
icon: const Icon(Icons.chevron_right),
|
||||
),
|
||||
],
|
||||
)
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -91,6 +91,7 @@ class _ColumnLayoutHeaderSettingsDeleteColumnState
|
||||
await Provider.of<AppRepository>(context, listen: false)
|
||||
.deleteColumn(widget.column.id);
|
||||
} catch (_) {
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
duration: Duration(seconds: 10),
|
||||
|
||||
@@ -112,6 +112,64 @@ class _CreateDeckState extends State<CreateDeck> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
bottom: Constants.spacingMiddle,
|
||||
),
|
||||
child: RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: const TextSpan(
|
||||
style: TextStyle(
|
||||
color: Constants.onSurface,
|
||||
fontSize: 14.0,
|
||||
),
|
||||
children: [
|
||||
TextSpan(
|
||||
text: 'We\'re excited to have you onboard at ',
|
||||
),
|
||||
TextSpan(
|
||||
text: 'FeedDeck',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text:
|
||||
'. We hope you enjoy your journey with us. If you have any questions or need assistance, feel free to reach out.',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
bottom: Constants.spacingMiddle,
|
||||
),
|
||||
child: RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: const TextSpan(
|
||||
style: TextStyle(
|
||||
color: Constants.onSurface,
|
||||
fontSize: 14.0,
|
||||
),
|
||||
children: [
|
||||
TextSpan(
|
||||
text:
|
||||
'Now it\'s time to create your first deck. A deck is a collection of columns and sources. Provide the name for your first deck and click on the ',
|
||||
),
|
||||
TextSpan(
|
||||
text: '"Create Deck"',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: ' button.',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
TextFormField(
|
||||
controller: _nameController,
|
||||
keyboardType: TextInputType.text,
|
||||
|
||||
@@ -195,9 +195,9 @@ class _DeckLayoutLargeState extends State<DeckLayoutLarge> {
|
||||
/// The drawer is used to display the [CreateColumn] widget, so that a
|
||||
/// user can add a new column without leaving the screen.
|
||||
drawer: ClipRRect(
|
||||
borderRadius: const BorderRadius.vertical(
|
||||
top: Radius.circular(Constants.spacingMiddle),
|
||||
bottom: Radius.circular(Constants.spacingMiddle),
|
||||
borderRadius: const BorderRadius.only(
|
||||
topRight: Radius.circular(Constants.spacingMiddle),
|
||||
bottomRight: Radius.circular(Constants.spacingMiddle),
|
||||
),
|
||||
child: Drawer(
|
||||
width: Constants.columnWidth,
|
||||
|
||||
@@ -41,7 +41,7 @@ class ItemDetailsMastodon extends StatelessWidget {
|
||||
.map((item) => item as String)
|
||||
.toList()
|
||||
: null,
|
||||
)
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -67,15 +67,8 @@ class ItemAudioPlayerControlButtons extends StatelessWidget {
|
||||
final playerState = snapshot.data;
|
||||
final processingState = playerState?.processingState;
|
||||
final playing = playerState?.playing;
|
||||
if (processingState == ProcessingState.loading ||
|
||||
processingState == ProcessingState.buffering) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.all(Constants.spacingSmall),
|
||||
width: 48.0,
|
||||
height: 48.0,
|
||||
child: const CircularProgressIndicator(),
|
||||
);
|
||||
} else if (playing != true) {
|
||||
|
||||
if (playing != true) {
|
||||
return IconButton(
|
||||
icon: const Icon(Icons.play_arrow),
|
||||
iconSize: 64.0,
|
||||
|
||||
@@ -35,6 +35,16 @@ class _ItemAudioPlayerSeekBarState extends State<ItemAudioPlayerSeekBar> {
|
||||
/// audio file.
|
||||
Duration get _remaining => widget.duration - widget.position;
|
||||
|
||||
/// [_printDuration] prints the provided [duration] in a human readable format
|
||||
/// `HH:mm:ss`.
|
||||
String _printDuration(Duration duration) {
|
||||
String negativeSign = duration.isNegative ? '-' : '';
|
||||
String twoDigits(int n) => n.toString().padLeft(2, '0');
|
||||
String twoDigitMinutes = twoDigits(duration.inMinutes.remainder(60).abs());
|
||||
String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60).abs());
|
||||
return '$negativeSign${twoDigits(duration.inHours)}:$twoDigitMinutes:$twoDigitSeconds';
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
@@ -110,10 +120,7 @@ class _ItemAudioPlayerSeekBarState extends State<ItemAudioPlayerSeekBar> {
|
||||
left: Constants.spacingMiddle,
|
||||
bottom: 0.0,
|
||||
child: Text(
|
||||
RegExp(r'((^0*[1-9]\d*:)?\d{2}:\d{2})\.\d+$')
|
||||
.firstMatch('${widget.position}')
|
||||
?.group(1) ??
|
||||
'${widget.position}',
|
||||
_printDuration(widget.position),
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
),
|
||||
@@ -121,10 +128,7 @@ class _ItemAudioPlayerSeekBarState extends State<ItemAudioPlayerSeekBar> {
|
||||
right: Constants.spacingMiddle,
|
||||
bottom: 0.0,
|
||||
child: Text(
|
||||
RegExp(r'((^0*[1-9]\d*:)?\d{2}:\d{2})\.\d+$')
|
||||
.firstMatch('$_remaining')
|
||||
?.group(1) ??
|
||||
'$_remaining',
|
||||
_printDuration(_remaining),
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -81,7 +81,7 @@ class ItemMediaGallery extends StatelessWidget {
|
||||
),
|
||||
Expanded(
|
||||
child: _buildSingleMedia(context, 1),
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -114,7 +114,7 @@ class ItemMediaGallery extends StatelessWidget {
|
||||
),
|
||||
Expanded(
|
||||
child: _buildSingleMedia(context, 2),
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -63,7 +63,7 @@ class ItemMediaGallery extends StatelessWidget {
|
||||
),
|
||||
Expanded(
|
||||
child: _buildSingleMedia(context, itemMedias![1]),
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -96,7 +96,7 @@ class ItemMediaGallery extends StatelessWidget {
|
||||
),
|
||||
Expanded(
|
||||
child: _buildSingleMedia(context, itemMedias![2]),
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -35,7 +35,7 @@ class SettingsAccountsGithub extends StatelessWidget {
|
||||
await Provider.of<ProfileRepository>(
|
||||
context,
|
||||
listen: false,
|
||||
).deleteGithubAccount();
|
||||
).githubDeleteAccount();
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ class _SettingsAccountsGithubAddState extends State<SettingsAccountsGithubAdd> {
|
||||
await Provider.of<ProfileRepository>(
|
||||
context,
|
||||
listen: false,
|
||||
).addGithubAccount(_tokenController.text);
|
||||
).githubAddAccount(_tokenController.text);
|
||||
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:feeddeck/repositories/app_repository.dart';
|
||||
import 'package:feeddeck/repositories/items_repository.dart';
|
||||
import 'package:feeddeck/utils/constants.dart';
|
||||
|
||||
/// The [SettingsDecksSelect] widget shows a list of the users decks, when the
|
||||
@@ -19,8 +20,13 @@ class _SettingsDecksSelectState extends State<SettingsDecksSelect> {
|
||||
/// [_selectDeck] sets the provided [deckId] as the active deck. The active
|
||||
/// deck is updated via the [selectDeck] method of the [AppRepository]. When
|
||||
/// the active deck is updated the user is redirected to the decks view.
|
||||
///
|
||||
/// Before the active deck is changed the [ItemsRepositoryStore] is cleared,
|
||||
/// to trigger a reload of the items once the deck is loaded.
|
||||
Future<void> _selectDeck(String deckId) async {
|
||||
try {
|
||||
ItemsRepositoryStore().clear();
|
||||
|
||||
await Provider.of<AppRepository>(context, listen: false)
|
||||
.selectDeck(deckId);
|
||||
if (!mounted) return;
|
||||
|
||||
198
app/lib/widgets/settings/premium/settings_premium.dart
Normal file
@@ -0,0 +1,198 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:feeddeck/models/profile.dart';
|
||||
import 'package:feeddeck/repositories/profile_repository.dart';
|
||||
import 'package:feeddeck/repositories/settings_repository.dart';
|
||||
import 'package:feeddeck/utils/constants.dart';
|
||||
import 'package:feeddeck/utils/fd_icons.dart';
|
||||
import 'package:feeddeck/widgets/general/logo.dart';
|
||||
import 'package:feeddeck/widgets/settings/premium/settings_premium_inapp.dart';
|
||||
import 'package:feeddeck/widgets/settings/premium/settings_premium_inapp_restore.dart';
|
||||
import 'package:feeddeck/widgets/settings/premium/settings_premium_stripe.dart';
|
||||
|
||||
class SettingsPremium extends StatelessWidget {
|
||||
const SettingsPremium({super.key});
|
||||
|
||||
/// [_showPaymentModal] show a modal to subscribe to FeedDeck Premium via
|
||||
/// Stripe on the web, Linux and Windows. On macOS, Android and iOS the modal
|
||||
/// to subscribe via in-app purchases is shown.
|
||||
void _showPaymentModal(BuildContext context) {
|
||||
if (kIsWeb || Platform.isLinux || Platform.isWindows) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
isDismissible: true,
|
||||
useSafeArea: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(
|
||||
top: Radius.circular(Constants.spacingMiddle),
|
||||
),
|
||||
),
|
||||
clipBehavior: Clip.antiAliasWithSaveLayer,
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: Constants.centeredFormMaxWidth,
|
||||
),
|
||||
builder: (BuildContext context) {
|
||||
return const SettingsPremiumStripe();
|
||||
},
|
||||
);
|
||||
} else if (Platform.isMacOS || Platform.isAndroid || Platform.isIOS) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
isDismissible: true,
|
||||
useSafeArea: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(
|
||||
top: Radius.circular(Constants.spacingMiddle),
|
||||
),
|
||||
),
|
||||
clipBehavior: Clip.antiAliasWithSaveLayer,
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: Constants.centeredFormMaxWidth,
|
||||
),
|
||||
builder: (BuildContext context) {
|
||||
return const SettingsPremiumInApp();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
ProfileRepository profile = Provider.of<ProfileRepository>(
|
||||
context,
|
||||
listen: true,
|
||||
);
|
||||
|
||||
/// If subscriptions are disabled, because the user uses a custom Supabase
|
||||
/// instance or if the profile is not initialized yet or if the user is
|
||||
/// already on the premium tier we do not show the option to subscribe to
|
||||
/// FeedDeck Premium.
|
||||
if (!SettingsRepository().subscriptionEnabled) {
|
||||
return Container();
|
||||
}
|
||||
|
||||
if (profile.status == FDProfileStatus.uninitialized) {
|
||||
return Container();
|
||||
}
|
||||
|
||||
if (profile.tier != FDProfileTier.free) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Card(
|
||||
color: Constants.primary,
|
||||
margin: const EdgeInsets.only(
|
||||
bottom: Constants.spacingSmall,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(
|
||||
Constants.spacingMiddle,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
Characters('You are using FeedDeck Premium')
|
||||
.replaceAll(
|
||||
Characters(''),
|
||||
Characters('\u{200B}'),
|
||||
)
|
||||
.toString(),
|
||||
maxLines: 1,
|
||||
style: const TextStyle(
|
||||
color: Constants.onPrimary,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Icon(
|
||||
FDIcons.feeddeck,
|
||||
color: Constants.onPrimary,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: Constants.spacingMiddle,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
child: GestureDetector(
|
||||
onTap: () => _showPaymentModal(context),
|
||||
child: Card(
|
||||
color: Constants.primary,
|
||||
margin: const EdgeInsets.only(
|
||||
bottom: Constants.spacingSmall,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: const Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.all(
|
||||
Constants.spacingMiddle,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Logo(size: 64),
|
||||
SizedBox(
|
||||
height: Constants.spacingSmall,
|
||||
),
|
||||
Text(
|
||||
'Subscribe to FeedDeck Premium',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Constants.onPrimary,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SettingsPremiumInAppRestore(),
|
||||
const SizedBox(
|
||||
height: Constants.spacingMiddle,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
254
app/lib/widgets/settings/premium/settings_premium_inapp.dart
Normal file
@@ -0,0 +1,254 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:purchases_flutter/purchases_flutter.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart' as supabase;
|
||||
|
||||
import 'package:feeddeck/models/profile.dart';
|
||||
import 'package:feeddeck/repositories/profile_repository.dart';
|
||||
import 'package:feeddeck/repositories/settings_repository.dart';
|
||||
import 'package:feeddeck/utils/constants.dart';
|
||||
import 'package:feeddeck/utils/fd_icons.dart';
|
||||
import 'package:feeddeck/widgets/general/elevated_button_progress_indicator.dart';
|
||||
|
||||
class SettingsPremiumInApp extends StatefulWidget {
|
||||
const SettingsPremiumInApp({super.key});
|
||||
|
||||
@override
|
||||
State<SettingsPremiumInApp> createState() => _SettingsPremiumInAppState();
|
||||
}
|
||||
|
||||
class _SettingsPremiumInAppState extends State<SettingsPremiumInApp> {
|
||||
late Future<Offering?> _futureFetchOfferings;
|
||||
bool _isLoading = false;
|
||||
|
||||
/// [_fetchOfferings] is used to fetch the Stripe checkout session
|
||||
/// link. For that we have to call the `stripe-create-checkout-session-v1`
|
||||
/// Supabase edge function. If the link is generated successfully, the
|
||||
/// function returns the url, which can then be opened by the user.
|
||||
Future<Offering?> _fetchOfferings() async {
|
||||
if (Platform.isAndroid) {
|
||||
await Purchases.configure(
|
||||
PurchasesConfiguration(
|
||||
SettingsRepository().revenueCatGooglePlayKey,
|
||||
)..appUserID = supabase.Supabase.instance.client.auth.currentUser!.id,
|
||||
);
|
||||
} else if (Platform.isMacOS || Platform.isIOS) {
|
||||
await Purchases.configure(
|
||||
PurchasesConfiguration(
|
||||
SettingsRepository().revenueCatAppStoreKey,
|
||||
)..appUserID = supabase.Supabase.instance.client.auth.currentUser!.id,
|
||||
);
|
||||
}
|
||||
|
||||
Offerings offerings = await Purchases.getOfferings();
|
||||
if (offerings.current != null) {
|
||||
return offerings.current;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// [_purchase] is used to purchase the provided [package]. If the purchase
|
||||
/// was successful, the user is notified. If the purchase failed, the user is
|
||||
/// notified as well.
|
||||
Future<void> _purchase(Package package) async {
|
||||
try {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
|
||||
CustomerInfo customerInfo = await Purchases.purchasePackage(package);
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
|
||||
if (!customerInfo.entitlements.all.containsKey('FeedDeck Premium')) {
|
||||
throw Exception('FeedDeck Premium entitlement not found.');
|
||||
}
|
||||
|
||||
if (customerInfo.entitlements.all['FeedDeck Premium']!.isActive) {
|
||||
if (!mounted) return;
|
||||
Provider.of<ProfileRepository>(
|
||||
context,
|
||||
listen: false,
|
||||
).setTier(FDProfileTier.premium);
|
||||
}
|
||||
|
||||
if (!mounted) return;
|
||||
Navigator.of(context).pop();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
duration: Duration(seconds: 10),
|
||||
backgroundColor: Constants.primary,
|
||||
showCloseIcon: true,
|
||||
content: Text(
|
||||
'FeedDeck Premium was successfully purchased.',
|
||||
style: TextStyle(color: Constants.onPrimary),
|
||||
),
|
||||
),
|
||||
);
|
||||
} on PlatformException catch (err) {
|
||||
final errorCode = PurchasesErrorHelper.getErrorCode(err);
|
||||
if (errorCode == PurchasesErrorCode.purchaseCancelledError) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
Navigator.of(context).pop();
|
||||
} else {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
Navigator.of(context).pop();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
duration: const Duration(seconds: 10),
|
||||
backgroundColor: Constants.error,
|
||||
showCloseIcon: true,
|
||||
content: Text(
|
||||
'In-app purchase failed: ${err.message}',
|
||||
style: const TextStyle(color: Constants.onError),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
Navigator.of(context).pop();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
duration: const Duration(seconds: 10),
|
||||
backgroundColor: Constants.error,
|
||||
showCloseIcon: true,
|
||||
content: Text(
|
||||
'In-app purchase failed: ${err.toString()}',
|
||||
style: const TextStyle(color: Constants.onError),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
setState(() {
|
||||
_futureFetchOfferings = _fetchOfferings();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
shape: const Border(
|
||||
bottom: BorderSide(
|
||||
color: Constants.dividerColor,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
title: const Text('FeedDeck Premium'),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(
|
||||
Icons.close,
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
body: FutureBuilder(
|
||||
future: _futureFetchOfferings,
|
||||
builder: (
|
||||
BuildContext context,
|
||||
AsyncSnapshot<Offering?> snapshot,
|
||||
) {
|
||||
return Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(Constants.spacingMiddle),
|
||||
child: SingleChildScrollView(
|
||||
child: snapshot.connectionState == ConnectionState.none ||
|
||||
snapshot.connectionState ==
|
||||
ConnectionState.waiting ||
|
||||
snapshot.hasError ||
|
||||
snapshot.data == null ||
|
||||
snapshot.data?.monthly == null
|
||||
? const Text('Loading ...')
|
||||
: MarkdownBody(
|
||||
selectable: true,
|
||||
data: '''
|
||||
You are currently using the free version of FeedDeck, which allows you to add up
|
||||
to 10 sources for the first 7 days. After that trial period your sources will
|
||||
not be updated anymore.
|
||||
|
||||
To use FeedDeck after the trial period with up to 1000 sources, you need to
|
||||
upgrade to a premium account. The premium account costs
|
||||
${snapshot.data?.monthly?.storeProduct.priceString} per month and can be
|
||||
canceled at any time.
|
||||
''',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: Constants.spacingSmall,
|
||||
),
|
||||
const Divider(
|
||||
color: Constants.dividerColor,
|
||||
height: 1,
|
||||
thickness: 1,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(Constants.spacingMiddle),
|
||||
child: ElevatedButton.icon(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Constants.primary,
|
||||
foregroundColor: Constants.onPrimary,
|
||||
maximumSize: const Size.fromHeight(
|
||||
Constants.elevatedButtonSize,
|
||||
),
|
||||
minimumSize: const Size.fromHeight(
|
||||
Constants.elevatedButtonSize,
|
||||
),
|
||||
),
|
||||
label: Text(
|
||||
snapshot.data?.monthly?.storeProduct.priceString != null
|
||||
? 'Subscribe to FeedDeck Premium for ${snapshot.data?.monthly?.storeProduct.priceString}'
|
||||
: 'Subscribe to FeedDeck Premium',
|
||||
),
|
||||
onPressed: snapshot.connectionState == ConnectionState.none ||
|
||||
snapshot.connectionState == ConnectionState.waiting ||
|
||||
snapshot.hasError ||
|
||||
snapshot.data == null ||
|
||||
snapshot.data?.monthly == null ||
|
||||
_isLoading
|
||||
? null
|
||||
: () => _purchase(snapshot.data!.monthly!),
|
||||
icon: snapshot.connectionState == ConnectionState.none ||
|
||||
snapshot.connectionState == ConnectionState.waiting ||
|
||||
snapshot.hasError ||
|
||||
snapshot.data == null ||
|
||||
snapshot.data?.monthly == null ||
|
||||
_isLoading
|
||||
? const ElevatedButtonProgressIndicator()
|
||||
: const Icon(FDIcons.feeddeck),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:purchases_flutter/purchases_flutter.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart' as supabase;
|
||||
|
||||
import 'package:feeddeck/models/profile.dart';
|
||||
import 'package:feeddeck/repositories/profile_repository.dart';
|
||||
import 'package:feeddeck/repositories/settings_repository.dart';
|
||||
import 'package:feeddeck/utils/constants.dart';
|
||||
import 'package:feeddeck/widgets/general/elevated_button_progress_indicator.dart';
|
||||
|
||||
class SettingsPremiumInAppRestore extends StatefulWidget {
|
||||
const SettingsPremiumInAppRestore({super.key});
|
||||
|
||||
@override
|
||||
State<SettingsPremiumInAppRestore> createState() =>
|
||||
_SettingsPremiumInAppRestoreState();
|
||||
}
|
||||
|
||||
class _SettingsPremiumInAppRestoreState
|
||||
extends State<SettingsPremiumInAppRestore> {
|
||||
bool _isLoading = false;
|
||||
|
||||
Future<void> _restore() async {
|
||||
try {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
|
||||
if (Platform.isAndroid) {
|
||||
await Purchases.configure(
|
||||
PurchasesConfiguration(
|
||||
SettingsRepository().revenueCatGooglePlayKey,
|
||||
)..appUserID = supabase.Supabase.instance.client.auth.currentUser!.id,
|
||||
);
|
||||
} else if (Platform.isMacOS || Platform.isIOS) {
|
||||
await Purchases.configure(
|
||||
PurchasesConfiguration(
|
||||
SettingsRepository().revenueCatAppStoreKey,
|
||||
)..appUserID = supabase.Supabase.instance.client.auth.currentUser!.id,
|
||||
);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
CustomerInfo customerInfo = await Purchases.restorePurchases();
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
|
||||
if (!customerInfo.entitlements.all.containsKey('FeedDeck Premium')) {
|
||||
throw Exception('FeedDeck Premium entitlement not found.');
|
||||
}
|
||||
|
||||
if (customerInfo.entitlements.all['FeedDeck Premium']!.isActive) {
|
||||
if (!mounted) return;
|
||||
Provider.of<ProfileRepository>(
|
||||
context,
|
||||
listen: false,
|
||||
).setTier(FDProfileTier.premium);
|
||||
}
|
||||
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
duration: Duration(seconds: 10),
|
||||
backgroundColor: Constants.primary,
|
||||
showCloseIcon: true,
|
||||
content: Text(
|
||||
'FeedDeck Premium was restored.',
|
||||
style: TextStyle(color: Constants.onPrimary),
|
||||
),
|
||||
),
|
||||
);
|
||||
} on PlatformException catch (err) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
final errorCode = PurchasesErrorHelper.getErrorCode(err);
|
||||
if (errorCode == PurchasesErrorCode.purchaseCancelledError) {
|
||||
return;
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
duration: const Duration(seconds: 10),
|
||||
backgroundColor: Constants.error,
|
||||
showCloseIcon: true,
|
||||
content: Text(
|
||||
'Restore purchase failed: ${err.message}',
|
||||
style: const TextStyle(color: Constants.onError),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
duration: const Duration(seconds: 10),
|
||||
backgroundColor: Constants.error,
|
||||
showCloseIcon: true,
|
||||
content: Text(
|
||||
'Restore purchase failed: ${err.toString()}',
|
||||
style: const TextStyle(color: Constants.onError),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// [buildIcon] return the provided icon or when the [_isLoading] state is
|
||||
/// `true` is returns a circular progress indicator.
|
||||
Widget buildIcon() {
|
||||
if (_isLoading) return const ElevatedButtonProgressIndicator();
|
||||
return Container();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
ProfileRepository profile = Provider.of<ProfileRepository>(
|
||||
context,
|
||||
listen: true,
|
||||
);
|
||||
|
||||
/// We do not display the restore button when subscriptions are disabled,
|
||||
/// the profile isn't initalized yet or a user is already subscribed to
|
||||
/// FeedDeck Premium.
|
||||
if (!SettingsRepository().subscriptionEnabled) {
|
||||
return Container();
|
||||
}
|
||||
|
||||
if (profile.status == FDProfileStatus.uninitialized) {
|
||||
return Container();
|
||||
}
|
||||
|
||||
if (profile.tier != FDProfileTier.free) {
|
||||
return Container();
|
||||
}
|
||||
|
||||
if (!kIsWeb && (Platform.isMacOS || Platform.isAndroid || Platform.isIOS)) {
|
||||
return MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
child: GestureDetector(
|
||||
onTap: () => _restore(),
|
||||
child: Card(
|
||||
color: Constants.secondary,
|
||||
margin: const EdgeInsets.only(
|
||||
bottom: Constants.spacingSmall,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(
|
||||
Constants.spacingMiddle,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
Characters('Restore Purchases')
|
||||
.replaceAll(
|
||||
Characters(''),
|
||||
Characters('\u{200B}'),
|
||||
)
|
||||
.toString(),
|
||||
maxLines: 1,
|
||||
style: const TextStyle(
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
buildIcon(),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Container();
|
||||
}
|
||||
}
|
||||
@@ -1,134 +1,32 @@
|
||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart' as supabase;
|
||||
|
||||
import 'package:feeddeck/models/profile.dart';
|
||||
import 'package:feeddeck/repositories/profile_repository.dart';
|
||||
import 'package:feeddeck/utils/api_exception.dart';
|
||||
import 'package:feeddeck/utils/constants.dart';
|
||||
import 'package:feeddeck/utils/fd_icons.dart';
|
||||
import 'package:feeddeck/utils/openurl.dart';
|
||||
import 'package:feeddeck/widgets/general/elevated_button_progress_indicator.dart';
|
||||
import 'package:feeddeck/widgets/general/logo.dart';
|
||||
|
||||
const _settingsPaymentBannerText = '''
|
||||
const _settingsPremiumStripeText = '''
|
||||
You are currently using the free version of FeedDeck, which allows you to add up
|
||||
to 10 sources for the first 7 days. After that trial period your sources will
|
||||
not be updated anymore.
|
||||
|
||||
To use FeedDeck after the trial period with up to 1000 sources you need to
|
||||
To use FeedDeck after the trial period with up to 1000 sources, you need to
|
||||
upgrade to a premium account. The premium account costs 5€ per month and can be
|
||||
canceled at any time.
|
||||
''';
|
||||
|
||||
class SettingsPaymentBanner extends StatelessWidget {
|
||||
const SettingsPaymentBanner({super.key});
|
||||
class SettingsPremiumStripe extends StatefulWidget {
|
||||
const SettingsPremiumStripe({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
ProfileRepository profile = Provider.of<ProfileRepository>(
|
||||
context,
|
||||
listen: true,
|
||||
);
|
||||
|
||||
if (profile.status == FDProfileStatus.uninitialized) {
|
||||
return Container();
|
||||
}
|
||||
|
||||
if (!kIsWeb) {
|
||||
return Container();
|
||||
}
|
||||
|
||||
if (profile.tier != FDProfileTier.free) {
|
||||
return Container();
|
||||
}
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
isDismissible: true,
|
||||
useSafeArea: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(
|
||||
top: Radius.circular(Constants.spacingMiddle),
|
||||
),
|
||||
),
|
||||
clipBehavior: Clip.antiAliasWithSaveLayer,
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: Constants.centeredFormMaxWidth,
|
||||
),
|
||||
builder: (BuildContext context) {
|
||||
return const SettingsPaymentBannerModal();
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Card(
|
||||
color: Constants.primary,
|
||||
margin: const EdgeInsets.only(
|
||||
bottom: Constants.spacingSmall,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(
|
||||
Constants.spacingMiddle,
|
||||
),
|
||||
child: Column(
|
||||
children: const [
|
||||
Logo(size: 64),
|
||||
SizedBox(
|
||||
height: Constants.spacingSmall,
|
||||
),
|
||||
Text(
|
||||
'Subscribe to FeedDeck Premium',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Constants.onPrimary,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: Constants.spacingMiddle,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
State<SettingsPremiumStripe> createState() => _SettingsPremiumStripeState();
|
||||
}
|
||||
|
||||
class SettingsPaymentBannerModal extends StatefulWidget {
|
||||
const SettingsPaymentBannerModal({super.key});
|
||||
|
||||
@override
|
||||
State<SettingsPaymentBannerModal> createState() =>
|
||||
_SettingsPaymentBannerModalState();
|
||||
}
|
||||
|
||||
class _SettingsPaymentBannerModalState
|
||||
extends State<SettingsPaymentBannerModal> {
|
||||
class _SettingsPremiumStripeState extends State<SettingsPremiumStripe> {
|
||||
late Future<String> _futureFetchCheckoutSessionLink;
|
||||
|
||||
/// [_fetchCheckoutSessionLink] is used to fetch the Stripe checkout session
|
||||
@@ -177,7 +75,7 @@ class _SettingsPaymentBannerModalState
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
title: const Text('Subscribe to FeedDeck Premium'),
|
||||
title: const Text('FeedDeck Premium'),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(
|
||||
@@ -203,7 +101,7 @@ class _SettingsPaymentBannerModalState
|
||||
child: SingleChildScrollView(
|
||||
child: MarkdownBody(
|
||||
selectable: true,
|
||||
data: _settingsPaymentBannerText,
|
||||
data: _settingsPremiumStripeText,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -25,9 +25,9 @@ class _SettingsProfileState extends State<SettingsProfile> {
|
||||
Widget build(BuildContext context) {
|
||||
Provider.of<AppRepository>(context, listen: true);
|
||||
|
||||
return Column(
|
||||
return const Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: const [
|
||||
children: [
|
||||
Text(
|
||||
'Profile',
|
||||
style: TextStyle(
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart' as supabase;
|
||||
|
||||
import 'package:feeddeck/models/profile.dart';
|
||||
import 'package:feeddeck/repositories/profile_repository.dart';
|
||||
import 'package:feeddeck/utils/api_exception.dart';
|
||||
import 'package:feeddeck/utils/constants.dart';
|
||||
import 'package:feeddeck/utils/openurl.dart';
|
||||
@@ -22,80 +24,86 @@ class SettingsProfileCustomerPortal extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (!kIsWeb) {
|
||||
return Container();
|
||||
}
|
||||
ProfileRepository profile = Provider.of<ProfileRepository>(
|
||||
context,
|
||||
listen: true,
|
||||
);
|
||||
|
||||
return MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
isDismissible: true,
|
||||
useSafeArea: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(
|
||||
top: Radius.circular(Constants.spacingMiddle),
|
||||
),
|
||||
),
|
||||
clipBehavior: Clip.antiAliasWithSaveLayer,
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: Constants.centeredFormMaxWidth,
|
||||
),
|
||||
builder: (BuildContext context) {
|
||||
return const SettingsProfileCustomerPortalModal();
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Card(
|
||||
color: Constants.secondary,
|
||||
margin: const EdgeInsets.only(
|
||||
bottom: Constants.spacingSmall,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(
|
||||
Constants.spacingMiddle,
|
||||
if (profile.tier == FDProfileTier.premium &&
|
||||
profile.subscriptionProvider == FDProfileSubscriptionProvider.stripe) {
|
||||
return MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
isDismissible: true,
|
||||
useSafeArea: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(
|
||||
top: Radius.circular(Constants.spacingMiddle),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
Characters('Customer Portal')
|
||||
.replaceAll(
|
||||
Characters(''),
|
||||
Characters('\u{200B}'),
|
||||
)
|
||||
.toString(),
|
||||
maxLines: 1,
|
||||
style: const TextStyle(
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
clipBehavior: Clip.antiAliasWithSaveLayer,
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: Constants.centeredFormMaxWidth,
|
||||
),
|
||||
builder: (BuildContext context) {
|
||||
return const SettingsProfileCustomerPortalModal();
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Card(
|
||||
color: Constants.secondary,
|
||||
margin: const EdgeInsets.only(
|
||||
bottom: Constants.spacingSmall,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(
|
||||
Constants.spacingMiddle,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
Characters('Customer Portal')
|
||||
.replaceAll(
|
||||
Characters(''),
|
||||
Characters('\u{200B}'),
|
||||
)
|
||||
.toString(),
|
||||
maxLines: 1,
|
||||
style: const TextStyle(
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const Icon(Icons.receipt),
|
||||
],
|
||||
const Icon(Icons.receipt),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
return Container();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,9 +127,9 @@ class _SettingsProfileCustomerPortalModalState
|
||||
/// Supabase edge function. If the link is generated successfully, the
|
||||
/// function returns the url, which can then be opened by the user.
|
||||
Future<String> _fetchCustomerPortalLink() async {
|
||||
final result = await Supabase.instance.client.functions.invoke(
|
||||
final result = await supabase.Supabase.instance.client.functions.invoke(
|
||||
'stripe-create-billing-portal-link-v1',
|
||||
method: HttpMethod.get,
|
||||
method: supabase.HttpMethod.get,
|
||||
);
|
||||
|
||||
if (result.status != 200) {
|
||||
|
||||
@@ -48,6 +48,7 @@ class _SettingsProfileOpenWebAppState extends State<SettingsProfileOpenWebApp> {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
duration: Duration(seconds: 10),
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:supabase_flutter/supabase_flutter.dart' as supabase;
|
||||
|
||||
import 'package:feeddeck/repositories/items_repository.dart';
|
||||
import 'package:feeddeck/utils/constants.dart';
|
||||
import 'package:feeddeck/widgets/general/elevated_button_progress_indicator.dart';
|
||||
import 'package:feeddeck/widgets/signin/signin.dart';
|
||||
@@ -20,12 +21,16 @@ class _SettingsProfileSignOutState extends State<SettingsProfileSignOut> {
|
||||
|
||||
/// [_signOut] signs out the currently authenticated user and redirects him
|
||||
/// to the [SignIn] screen. This will sign out the user from all devices.
|
||||
///
|
||||
/// Before the user is signed out the [ItemsRepositoryStore] is cleared, to
|
||||
/// trigger a reload of the items once the user is signed in again.
|
||||
Future<void> _signOut() async {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
|
||||
try {
|
||||
ItemsRepositoryStore().clear();
|
||||
await supabase.Supabase.instance.client.auth.signOut();
|
||||
|
||||
setState(() {
|
||||
|
||||
@@ -6,9 +6,9 @@ import 'package:feeddeck/repositories/profile_repository.dart';
|
||||
import 'package:feeddeck/utils/constants.dart';
|
||||
import 'package:feeddeck/widgets/settings/accounts/settings_accounts.dart';
|
||||
import 'package:feeddeck/widgets/settings/decks/settings_decks.dart';
|
||||
import 'package:feeddeck/widgets/settings/premium/settings_premium.dart';
|
||||
import 'package:feeddeck/widgets/settings/profile/settings_profile.dart';
|
||||
import 'package:feeddeck/widgets/settings/settings_info.dart';
|
||||
import 'package:feeddeck/widgets/settings/settings_payment_banner.dart';
|
||||
|
||||
/// The [Settings] widget implements the settings page for the FeedDeck app. The
|
||||
/// page is used to display all the users information and to provide a way where
|
||||
@@ -54,11 +54,11 @@ class _SettingsState extends State<Settings> {
|
||||
padding: const EdgeInsets.all(
|
||||
Constants.spacingMiddle,
|
||||
),
|
||||
child: Column(
|
||||
child: const Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: const [
|
||||
SettingsPaymentBanner(),
|
||||
children: [
|
||||
SettingsPremium(),
|
||||
|
||||
/// Display all decks. Here the user can switch the active
|
||||
/// deck, he can delete a deck or update the name of a
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
@@ -157,6 +160,40 @@ class _SettingsInfoState extends State<SettingsInfo> {
|
||||
} catch (_) {}
|
||||
},
|
||||
),
|
||||
_buildItem(
|
||||
'Get Started',
|
||||
const Icon(Icons.help),
|
||||
() {
|
||||
try {
|
||||
if (kIsWeb ||
|
||||
Platform.isLinux ||
|
||||
Platform.isMacOS ||
|
||||
Platform.isWindows) {
|
||||
openUrl('https://feeddeck.app/get-started/desktop');
|
||||
} else {
|
||||
openUrl('https://feeddeck.app/get-started/mobile');
|
||||
}
|
||||
} catch (_) {}
|
||||
},
|
||||
),
|
||||
_buildItem(
|
||||
'Terms & Conditions',
|
||||
const Icon(Icons.policy),
|
||||
() {
|
||||
try {
|
||||
openUrl('https://feeddeck.app/terms-and-conditions');
|
||||
} catch (_) {}
|
||||
},
|
||||
),
|
||||
_buildItem(
|
||||
'Privacy Policy',
|
||||
const Icon(Icons.security),
|
||||
() {
|
||||
try {
|
||||
openUrl('https://feeddeck.app/privacy-policy');
|
||||
} catch (_) {}
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -154,12 +154,12 @@ class _SignInState extends State<SignIn> {
|
||||
/// [_signInWithApple] handles the sign in of a user via his Apple account.
|
||||
Future<void> _signInWithApple() async {
|
||||
try {
|
||||
if (!kIsWeb && Platform.isIOS) {
|
||||
/// On iOS we are using the `signInWithApple` method of the Supabase
|
||||
/// client instead of the `signInWithOAuth` method, so that the user is
|
||||
/// not redirected for the sign in. Since the sign in is completly
|
||||
/// handled within the app we have to call the `init` method of the
|
||||
/// [AppRepository] to load the user data from Supabase.
|
||||
if (!kIsWeb && (Platform.isIOS || Platform.isMacOS)) {
|
||||
/// On iOS and macOS we are using the `signInWithApple` method of the
|
||||
/// Supabase client instead of the `signInWithOAuth` method, so that the
|
||||
/// user is not redirected for the sign in. Since the sign in is
|
||||
/// completly handled within the app we have to call the `init` method
|
||||
/// of the [AppRepository] to load the user data from Supabase.
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
_error = '';
|
||||
@@ -186,10 +186,9 @@ class _SignInState extends State<SignIn> {
|
||||
),
|
||||
(route) => false,
|
||||
);
|
||||
} else if (!kIsWeb &&
|
||||
(Platform.isLinux || Platform.isMacOS || Platform.isWindows)) {
|
||||
/// On Linux, macOS and Windows we have to use the [DesktopLoginManager]
|
||||
/// to handle the login via the users Apple account. Once the sing in
|
||||
} else if (!kIsWeb && (Platform.isLinux || Platform.isWindows)) {
|
||||
/// On Linux and Windows we have to use the [DesktopLoginManager] to
|
||||
/// handle the login via the users Apple account. Once the sing in
|
||||
/// process is finished we have to call the init method of the
|
||||
/// [AppRepository] to load the users data.
|
||||
setState(() {
|
||||
@@ -349,8 +348,8 @@ class _SignInState extends State<SignIn> {
|
||||
/// his Apple account.
|
||||
ElevatedButton.icon(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xff000000),
|
||||
foregroundColor: const Color(0xffffffff),
|
||||
backgroundColor: const Color(0xffffffff),
|
||||
foregroundColor: const Color(0xff000000),
|
||||
maximumSize: const Size.fromHeight(
|
||||
Constants.elevatedButtonSize,
|
||||
),
|
||||
|
||||
@@ -14,8 +14,11 @@ import 'package:feeddeck/widgets/source/add/add_source_form.dart';
|
||||
const _helpText = '''
|
||||
The Nitter source can be used to add an RSS feed for Nitter:
|
||||
|
||||
- **RSS Feed**: `https://nitter.net/rico_berger/rss` or `https://nitter.net/search/rss?f=tweets&q=FeedDeck`
|
||||
- **Username**: `@rico_berger`
|
||||
- **Search Term**: `FeedDeck`
|
||||
|
||||
**Note:** We recommend that you use your own Nitter instance to avoid rate limiting.
|
||||
''';
|
||||
|
||||
/// The [AddSourceNitter] widget is used to display the form to add a new Nitter
|
||||
|
||||
@@ -87,6 +87,7 @@ class _SourceListItemState extends State<SourceListItem> {
|
||||
AppRepository app = Provider.of<AppRepository>(context, listen: false);
|
||||
await app.deleteSource(widget.columnId, widget.source.id);
|
||||
} catch (_) {
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
duration: Duration(seconds: 10),
|
||||
|
||||
9
app/linux/flatpak/app.feeddeck.feeddeck.desktop
Normal file
@@ -0,0 +1,9 @@
|
||||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Type=Application
|
||||
Name=FeedDeck
|
||||
Comment=Follow your RSS and Social Media Feeds
|
||||
Categories=Utility
|
||||
Icon=app.feeddeck.feeddeck
|
||||
Terminal=false
|
||||
Exec=feeddeck
|
||||
167
app/linux/flatpak/app.feeddeck.feeddeck.metainfo.xml
Normal file
@@ -0,0 +1,167 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop-application">
|
||||
<id>app.feeddeck.feeddeck</id>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>MIT</project_license>
|
||||
<name>FeedDeck</name>
|
||||
<summary>Follow your RSS and Social Media Feeds</summary>
|
||||
<developer_name>Rico Berger</developer_name>
|
||||
|
||||
<url type="homepage">https://feeddeck.app</url>
|
||||
<url type="bugtracker">https://github.com/feeddeck/feeddeck/issues</url>
|
||||
<url type="contribute">https://github.com/feeddeck/feeddeck</url>
|
||||
<url type="donation">https://github.com/sponsors/ricoberger</url>
|
||||
<url type="vcs-browser">https://github.com/feeddeck/feeddeck</url>
|
||||
|
||||
<launchable type="desktop-id">app.feeddeck.feeddeck.desktop</launchable>
|
||||
|
||||
<provides>
|
||||
<id>app.feeddeck.feeddeck</id>
|
||||
</provides>
|
||||
|
||||
<content_rating type="oars-1.1">
|
||||
<content_attribute id="money-purchasing">intense</content_attribute>
|
||||
</content_rating>
|
||||
|
||||
<description>
|
||||
<p>
|
||||
FeedDeck is an open source RSS and social media feed reader, inspired by TweetDeck. FeedDeck allows you to follow your favorite feeds in one place on all platforms. FeedDeck is written in Flutter and uses Supabase and Deno as it's backend.
|
||||
</p>
|
||||
<ul>
|
||||
<li>Available for mobile and desktop: FeedDeck provides the same experience for mobile and desktop with nearly 100% code sharing.</li>
|
||||
<li>RSS and Social Media Feeds: Follow your favorite RSS and social media feeds.</li>
|
||||
<li>News: Get the latest news from your favorite RSS feeds and Google News.</li>
|
||||
<li>Social Media: Follow your friends and favorite topics on Medium, Nitter, Reddit, Tumblr and X.</li>
|
||||
<li>GitHub: Get your GitHub notifications and follow your repository activities.</li>
|
||||
<li>Podcasts: Follow and listen to your favorite podcasts, via the built-in podcast player.</li>
|
||||
<li>YouTube: Follow and view your favorite YouTube channels.</li>
|
||||
</ul>
|
||||
</description>
|
||||
|
||||
<keywords>
|
||||
<keyword>RSS</keyword>
|
||||
<keyword>Social Media</keyword>
|
||||
<keyword>Reader</keyword>
|
||||
</keywords>
|
||||
|
||||
<categories>
|
||||
<category>System</category>
|
||||
<category>Utilities</category>
|
||||
</categories>
|
||||
|
||||
<releases>
|
||||
<release version="v1.1.1" date="2023-10-21">
|
||||
<description>
|
||||
<p>Fixed</p>
|
||||
<ul>
|
||||
<li>#46: [core] Fix Number of Loaded Items per Fetch @ricoberger</li>
|
||||
<li>#45: [core] Fix ItemsRepository Status @ricoberger</li>
|
||||
<li>#44: [core] Fix Border Radius for Drawer @ricoberger</li>
|
||||
<li>#43: [core] Fix Status Bar for iOS @ricoberger</li>
|
||||
<li>#42: [podcast] Fix Audio Player for Windows and Linux @ricoberger</li>
|
||||
<li>#37: [podcast] Fix Duration and Play Button @ricoberger</li>
|
||||
</ul>
|
||||
|
||||
<p>Changed</p>
|
||||
<ul>
|
||||
<li>#48: [core] Improve Android App Icons @ricoberger</li>
|
||||
<li>#47: [core] Clear Cached Items @ricoberger</li>
|
||||
<li>#39: [core] Add Privacy Policy and Terms & Conditions @ricoberger</li>
|
||||
<li>#38: [core] Enable In-App Purchases for Android @ricoberger</li>
|
||||
</ul>
|
||||
</description>
|
||||
|
||||
<url>https://github.com/feeddeck/feeddeck/releases/tag/v1.1.1</url>
|
||||
</release>
|
||||
<release version="v1.1.0" date="2023-10-16">
|
||||
<description>
|
||||
<p>Added</p>
|
||||
<ul>
|
||||
<li>#31: [core] Add Dependabot Configuration @ricoberger</li>
|
||||
<li>#24: [core] Add In-App Purchases @ricoberger</li>
|
||||
<li>#16: [core] Add "Get Started" Guide @ricoberger</li>
|
||||
<li>#15: [core] Add Flatpak @ricoberger</li>
|
||||
</ul>
|
||||
|
||||
<p>Fixed</p>
|
||||
<ul>
|
||||
<li>#35: [core] Fix Google Client ID @ricoberger</li>
|
||||
<li>#28: [core] Fix Title Alignment @ricoberger</li>
|
||||
<li>#27: [core] Fix Vertical Scrolling @ricoberger</li>
|
||||
<li>#22: [core] Fix Update of Read State for Large List of Items @ricoberger</li>
|
||||
<li>#20: [youtube] Add Missing URL in isYoutubeUrl Function @ricoberger</li>
|
||||
</ul>
|
||||
|
||||
<p>Changed</p>
|
||||
<ul>
|
||||
<li>#34: [core] Rework Profile Edge Function @ricoberger</li>
|
||||
<li>#33: Bump the github-actions group with 5 updates @dependabot</li>
|
||||
<li>#32: Bump the docker group in /supabase/functions/_cmd with 1 update @dependabot</li>
|
||||
<li>#30: [core] Update NPM Packages @ricoberger</li>
|
||||
<li>#29: [core] Update Flutter to v3.13.7 @ricoberger</li>
|
||||
<li>#23: [core] Add Flatpak Files to Build Archive @ricoberger</li>
|
||||
<li>#21: [core] Use Published Date for Item Ingestion @ricoberger</li>
|
||||
<li>#19: [nitter] Allow Usage of Custom Nitter Instances @ricoberger</li>
|
||||
<li>#18: [rss] Allow RSS Feeds without "published" Field @ricoberger</li>
|
||||
<li>#17: [podcast] Improve Parsing @ricoberger</li>
|
||||
<li>#14: [core] Fix Issues with App Submission @ricoberger</li>
|
||||
</ul>
|
||||
</description>
|
||||
|
||||
<url>https://github.com/feeddeck/feeddeck/releases/tag/v1.1.0</url>
|
||||
</release>
|
||||
<release version="v1.0.0" date="2023-09-17">
|
||||
<description>
|
||||
<p>Added</p>
|
||||
<ul>
|
||||
<li>#10: [core] Add Continuous Delivery for Landing Page @ricoberger</li>
|
||||
<li>#7: [core] Add Continuous Delivery for Supabase @ricoberger</li>
|
||||
<li>#8: [core] Add Info Section to Settings @ricoberger</li>
|
||||
<li>#6: [core] Add Continuous Delivery for Desktop Apps @ricoberger</li>
|
||||
<li>#4: Add GitHub Action to Publish Web Version @ricoberger</li>
|
||||
<li>#3: [core] Add Continuous Delivery and Release Workflow @ricoberger</li>
|
||||
</ul>
|
||||
|
||||
<p>Fixed</p>
|
||||
<ul>
|
||||
<li>#9: [core] Fix Continuous Delivery for Supabase @ricoberger</li>
|
||||
</ul>
|
||||
|
||||
<p>Changed</p>
|
||||
<ul>
|
||||
<li>#12: Prepare v1.0.0 Release @ricoberger</li>
|
||||
<li>#5: [core] Improve Media Handling @ricoberger</li>
|
||||
<li>#2: [nitter] Add Media Gallery to Details View @ricoberger</li>
|
||||
<li>#1: [nitter] Add Basic Authentication @ricoberger</li>
|
||||
</ul>
|
||||
</description>
|
||||
|
||||
<url>https://github.com/feeddeck/feeddeck/releases/tag/v1.0.0</url>
|
||||
</release>
|
||||
</releases>
|
||||
|
||||
<supports>
|
||||
<control>pointing</control>
|
||||
<control>keyboard</control>
|
||||
<control>touch</control>
|
||||
<control>tablet</control>
|
||||
</supports>
|
||||
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<image>https://raw.githubusercontent.com/feeddeck/feeddeck/main/app/linux/flatpak/screenshots/1.png</image>
|
||||
</screenshot>
|
||||
<screenshot type="default">
|
||||
<image>https://raw.githubusercontent.com/feeddeck/feeddeck/main/app/linux/flatpak/screenshots/2.png</image>
|
||||
</screenshot>
|
||||
<screenshot type="default">
|
||||
<image>https://raw.githubusercontent.com/feeddeck/feeddeck/main/app/linux/flatpak/screenshots/3.png</image>
|
||||
</screenshot>
|
||||
<screenshot type="default">
|
||||
<image>https://raw.githubusercontent.com/feeddeck/feeddeck/main/app/linux/flatpak/screenshots/4.png</image>
|
||||
</screenshot>
|
||||
<screenshot type="default">
|
||||
<image>https://raw.githubusercontent.com/feeddeck/feeddeck/main/app/linux/flatpak/screenshots/5.png</image>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
</component>
|
||||
12
app/linux/flatpak/app.feeddeck.feeddeck.svg
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 4096 4096" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g id="icon-linux">
|
||||
<g id="bg" transform="matrix(1.77687,0,0,1.77687,-1011.62,-1480.98)">
|
||||
<circle cx="1721.91" cy="1986.06" r="1152.59" style="fill:rgb(73,211,180);"/>
|
||||
</g>
|
||||
<g id="fg" transform="matrix(13.5357,0,0,13.0255,-2722.19,-2672.07)">
|
||||
<path d="M443.567,272.226C438.383,276.258 434.063,278.274 430.607,278.274C423.695,278.274 416.783,274.146 409.871,265.89L369.263,293.826C362.927,298.434 359.759,304.194 359.759,311.106L359.759,429.186L359.471,429.474C359.471,432.354 358.559,435.234 356.735,438.114C354.911,440.994 352.943,442.434 350.831,442.434L350.255,442.434L350.255,439.554L347.951,442.722C345.071,442.53 337.583,439.17 325.487,432.642L325.487,432.93C313.199,425.826 302.927,422.274 294.671,422.274C286.223,422.274 278.447,425.442 271.343,431.778C268.079,434.658 265.439,438.162 263.423,442.29C261.407,446.418 260.111,451.266 259.535,456.834C263.759,451.842 268.943,449.058 275.087,448.482C276.239,448.482 277.007,448.386 277.391,448.194L277.967,448.194C282.191,448.194 290.351,450.594 302.447,455.394C308.207,457.698 315.215,458.85 323.471,458.85C334.991,458.85 347.471,455.778 360.911,449.634C376.271,442.53 385.871,434.082 389.711,424.29C390.287,422.946 390.575,421.602 390.575,420.258L390.863,370.722L410.735,370.722L410.735,431.778L421.391,431.778L421.391,301.314C425.231,300.354 428.687,298.482 431.759,295.698C434.831,292.914 437.807,289.314 440.687,284.898C443.183,281.058 444.431,278.274 444.431,276.546L444.719,276.258C444.719,275.49 444.911,274.53 445.295,273.378L443.567,272.226ZM356.015,297.282C350.447,298.242 345.503,299.874 341.183,302.178C336.863,304.482 332.975,307.266 329.519,310.53C321.647,317.634 317.711,326.562 317.711,337.314L317.711,338.754L317.999,339.042L317.999,340.194C317.231,340.194 316.655,340.098 316.271,339.906L313.679,339.906C298.127,339.906 290.351,347.874 290.351,363.81C290.351,368.418 291.695,372.498 294.383,376.05C297.071,379.602 300.719,381.378 305.327,381.378L305.327,379.362L305.039,379.074L305.039,377.922L304.751,377.634C304.751,373.218 308.015,371.01 314.543,371.01L316.559,371.01L317.135,371.298L318.287,371.298L318.287,413.634C318.095,414.018 317.951,414.498 317.855,415.074C317.759,415.65 317.615,416.13 317.423,416.514C317.039,417.282 316.703,418.194 316.415,419.25C316.127,420.306 315.887,421.026 315.695,421.41L318.575,421.41L319.151,421.122L319.727,421.122L320.015,420.834C322.703,420.834 326.351,419.202 330.959,415.938C344.399,407.106 351.119,396.93 351.119,385.41L351.119,310.818C351.119,308.706 351.647,306.45 352.703,304.05C353.759,301.65 355.055,300.162 356.591,299.586L356.015,297.282ZM375.023,266.754C370.415,270.978 365.231,273.09 359.471,273.09C351.407,273.09 345.647,272.226 342.191,270.498L341.615,270.498L341.327,270.21C338.063,269.634 335.375,269.106 333.263,268.626C331.151,268.146 329.615,267.81 328.655,267.618L325.775,267.618C320.207,267.042 317.231,266.562 316.847,266.178L314.831,267.042C298.319,267.426 286.799,273.186 280.271,284.322C277.391,289.314 275.951,293.73 275.951,297.57L275.951,300.162C282.671,295.938 286.991,293.826 288.911,293.826L290.063,293.826L290.351,293.538C294.767,293.538 302.063,294.594 312.239,296.706C321.839,298.818 329.039,299.874 333.839,299.874L334.127,300.162L335.279,300.162C344.687,300.162 353.615,297.09 362.063,290.946C371.087,284.418 376.079,276.642 377.039,267.618L375.023,266.754ZM409.583,301.89C409.775,301.89 409.919,301.938 410.015,302.034C410.111,302.13 410.351,302.082 410.735,301.89L410.735,340.482L390.863,340.482L390.863,294.402C397.967,299.394 404.207,301.89 409.583,301.89Z" style="fill:rgb(31,34,41);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.0 KiB |
BIN
app/linux/flatpak/screenshots/1.png
Normal file
|
After Width: | Height: | Size: 2.3 MiB |
BIN
app/linux/flatpak/screenshots/2.png
Normal file
|
After Width: | Height: | Size: 2.2 MiB |
BIN
app/linux/flatpak/screenshots/3.png
Normal file
|
After Width: | Height: | Size: 2.0 MiB |
BIN
app/linux/flatpak/screenshots/4.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
app/linux/flatpak/screenshots/5.png
Normal file
|
After Width: | Height: | Size: 981 KiB |
@@ -6,11 +6,15 @@
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <media_kit_libs_linux/media_kit_libs_linux_plugin.h>
|
||||
#include <screen_retriever/screen_retriever_plugin.h>
|
||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||
#include <window_manager/window_manager_plugin.h>
|
||||
|
||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) media_kit_libs_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "MediaKitLibsLinuxPlugin");
|
||||
media_kit_libs_linux_plugin_register_with_registrar(media_kit_libs_linux_registrar);
|
||||
g_autoptr(FlPluginRegistrar) screen_retriever_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverPlugin");
|
||||
screen_retriever_plugin_register_with_registrar(screen_retriever_registrar);
|
||||
|
||||
@@ -3,12 +3,14 @@
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
media_kit_libs_linux
|
||||
screen_retriever
|
||||
url_launcher_linux
|
||||
window_manager
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
media_kit_native_event_loop
|
||||
)
|
||||
|
||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||
|
||||
@@ -11,6 +11,7 @@ import audio_session
|
||||
import just_audio
|
||||
import package_info_plus
|
||||
import path_provider_foundation
|
||||
import purchases_flutter
|
||||
import screen_retriever
|
||||
import shared_preferences_foundation
|
||||
import sign_in_with_apple
|
||||
@@ -25,6 +26,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin"))
|
||||
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
PurchasesFlutterPlugin.register(with: registry.registrar(forPlugin: "PurchasesFlutterPlugin"))
|
||||
ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin"))
|
||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||
SignInWithApplePlugin.register(with: registry.registrar(forPlugin: "SignInWithApplePlugin"))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
platform :osx, '10.14'
|
||||
platform :osx, '11.0'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
||||
@@ -11,11 +11,19 @@ PODS:
|
||||
- FMDB/standard (2.7.5)
|
||||
- just_audio (0.0.1):
|
||||
- FlutterMacOS
|
||||
- media_kit_native_event_loop (1.0.0):
|
||||
- FlutterMacOS
|
||||
- package_info_plus (0.0.1):
|
||||
- FlutterMacOS
|
||||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- purchases_flutter (6.0.0):
|
||||
- FlutterMacOS
|
||||
- PurchasesHybridCommon (= 7.0.0)
|
||||
- PurchasesHybridCommon (7.0.0):
|
||||
- RevenueCat (= 4.27.0)
|
||||
- RevenueCat (4.27.0)
|
||||
- screen_retriever (0.0.1):
|
||||
- FlutterMacOS
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
@@ -37,10 +45,12 @@ DEPENDENCIES:
|
||||
- audio_session (from `Flutter/ephemeral/.symlinks/plugins/audio_session/macos`)
|
||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||
- just_audio (from `Flutter/ephemeral/.symlinks/plugins/just_audio/macos`)
|
||||
- media_kit_native_event_loop (from `Flutter/ephemeral/.symlinks/plugins/media_kit_native_event_loop/macos`)
|
||||
- package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
|
||||
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos`)
|
||||
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- purchases_flutter (from `Flutter/ephemeral/.symlinks/plugins/purchases_flutter/macos`)
|
||||
- screen_retriever (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos`)
|
||||
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/macos`)
|
||||
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- sign_in_with_apple (from `Flutter/ephemeral/.symlinks/plugins/sign_in_with_apple/macos`)
|
||||
- sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`)
|
||||
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
||||
@@ -49,6 +59,8 @@ DEPENDENCIES:
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- FMDB
|
||||
- PurchasesHybridCommon
|
||||
- RevenueCat
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
app_links:
|
||||
@@ -61,14 +73,18 @@ EXTERNAL SOURCES:
|
||||
:path: Flutter/ephemeral
|
||||
just_audio:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/just_audio/macos
|
||||
media_kit_native_event_loop:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/media_kit_native_event_loop/macos
|
||||
package_info_plus:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos
|
||||
path_provider_foundation:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
|
||||
purchases_flutter:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/purchases_flutter/macos
|
||||
screen_retriever:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos
|
||||
shared_preferences_foundation:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/macos
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
|
||||
sign_in_with_apple:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/sign_in_with_apple/macos
|
||||
sqflite:
|
||||
@@ -85,15 +101,19 @@ SPEC CHECKSUMS:
|
||||
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
||||
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
||||
just_audio: 9b67ca7b97c61cfc9784ea23cd8cc55eb226d489
|
||||
media_kit_native_event_loop: d20622d35dd6d06fe71223976bd70a2bcf595dce
|
||||
package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce
|
||||
path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9
|
||||
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
|
||||
purchases_flutter: 9aad80bf27960c38fdeafc27ab066cb55615aed5
|
||||
PurchasesHybridCommon: af3b2413f9cb999bc1fdca44770bdaf39dfb89fa
|
||||
RevenueCat: 84fbe2eb9bbf63e1abf346ccd3ff9ee45d633e3b
|
||||
screen_retriever: 59634572a57080243dd1bf715e55b6c54f241a38
|
||||
shared_preferences_foundation: 986fc17f3d3251412d18b0265f9c64113a8c2472
|
||||
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
|
||||
sign_in_with_apple: a9e97e744e8edc36aefc2723111f652102a7a727
|
||||
sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea
|
||||
url_launcher_macos: 5335912b679c073563f29d89d33d10d459f95451
|
||||
url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95
|
||||
window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8
|
||||
|
||||
PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7
|
||||
PODFILE CHECKSUM: 8d40c19d3cbdb380d870685c3a564c989f1efa52
|
||||
|
||||
COCOAPODS: 1.12.1
|
||||
COCOAPODS: 1.13.0
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
|
||||
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
|
||||
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
|
||||
553BE2622AC0648A002EA0C0 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 553BE2612AC0648A002EA0C0 /* StoreKit.framework */; };
|
||||
FBF50439F2C4D0BF615EFED2 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27D60858A3CD81E41E2CDBF2 /* Pods_Runner.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@@ -70,6 +71,8 @@
|
||||
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
|
||||
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
|
||||
46A27EFECA16837D10C377EF /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||
553BE2612AC0648A002EA0C0 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
|
||||
55A996D72AB9F2F200780025 /* RunnerDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerDebug.entitlements; sourceTree = "<group>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
|
||||
A5EAD2A55E3BD9F0DF253072 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
@@ -81,6 +84,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
FBF50439F2C4D0BF615EFED2 /* Pods_Runner.framework in Frameworks */,
|
||||
553BE2622AC0648A002EA0C0 /* StoreKit.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -152,6 +156,7 @@
|
||||
33FAB671232836740065AC1E /* Runner */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
55A996D72AB9F2F200780025 /* RunnerDebug.entitlements */,
|
||||
33CC10F02044A3C60003C045 /* AppDelegate.swift */,
|
||||
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */,
|
||||
33E51913231747F40026EE4D /* DebugProfile.entitlements */,
|
||||
@@ -165,6 +170,7 @@
|
||||
D73912EC22F37F3D000D13A0 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
553BE2612AC0648A002EA0C0 /* StoreKit.framework */,
|
||||
27D60858A3CD81E41E2CDBF2 /* Pods_Runner.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
@@ -202,7 +208,7 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0920;
|
||||
LastUpgradeCheck = 1300;
|
||||
LastUpgradeCheck = 1430;
|
||||
ORGANIZATIONNAME = "";
|
||||
TargetAttributes = {
|
||||
33CC10EC2044A3C60003C045 = {
|
||||
@@ -419,6 +425,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEVELOPMENT_TEAM = 75AP6HWLUD;
|
||||
@@ -428,6 +435,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
@@ -546,7 +554,8 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/RunnerDebug.entitlements;
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEVELOPMENT_TEAM = 75AP6HWLUD;
|
||||
@@ -556,6 +565,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@@ -569,6 +579,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEVELOPMENT_TEAM = 75AP6HWLUD;
|
||||
@@ -578,6 +589,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1300"
|
||||
LastUpgradeVersion = "1430"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.developer.applesignin</key>
|
||||
<array>
|
||||
<string>Default</string>
|
||||
</array>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.developer.applesignin</key>
|
||||
<array>
|
||||
<string>Default</string>
|
||||
</array>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
|
||||
18
app/macos/Runner/RunnerDebug.entitlements
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.developer.applesignin</key>
|
||||
<array>
|
||||
<string>Default</string>
|
||||
</array>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.server</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
492
app/pubspec.lock
@@ -16,10 +16,10 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
# In Windows, build-name is used as the major, minor, and patch parts
|
||||
# of the product and file versions while build-number is used as the build suffix.
|
||||
version: 1.0.0+2
|
||||
version: 1.1.1+7
|
||||
|
||||
environment:
|
||||
sdk: '>=2.19.6 <3.0.0'
|
||||
sdk: '>=3.1.3 <4.0.0'
|
||||
|
||||
# Dependencies specify other packages that your package needs in order to work.
|
||||
# To automatically upgrade your package dependencies to the latest versions
|
||||
@@ -47,10 +47,10 @@ dependencies:
|
||||
intl: ^0.18.1
|
||||
just_audio: ^0.9.32
|
||||
just_audio_background: ^0.0.1-beta.10
|
||||
just_audio_windows: ^0.2.0
|
||||
just_audio_mpv: ^0.1.6
|
||||
just_audio_media_kit: ^1.0.0
|
||||
package_info_plus: ^4.1.0
|
||||
provider: ^6.0.4
|
||||
purchases_flutter: ^6.0.0
|
||||
rxdart: ^0.27.7
|
||||
scroll_to_index: ^3.0.1
|
||||
shared_preferences: ^2.1.0
|
||||
@@ -160,7 +160,7 @@ msix_config:
|
||||
publisher_display_name: Rico Berger
|
||||
identity_name: 26077RicoBerger.FeedDeck
|
||||
publisher: CN=7740451A-C179-450A-B346-7231CA231332
|
||||
msix_version: 1.0.0.0
|
||||
msix_version: 1.1.1.0
|
||||
logo_path: templates/app-icon/windows.png
|
||||
languages: en-us
|
||||
capabilities: internetClient
|
||||
|
||||
|
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 181 KiB After Width: | Height: | Size: 182 KiB |
12
app/templates/app-icon/linux.svg
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 4096 4096" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g id="icon-linux">
|
||||
<g id="bg" transform="matrix(1.77687,0,0,1.77687,-1011.62,-1480.98)">
|
||||
<circle cx="1721.91" cy="1986.06" r="1152.59" style="fill:rgb(73,211,180);"/>
|
||||
</g>
|
||||
<g id="fg" transform="matrix(13.5357,0,0,13.0255,-2722.19,-2672.07)">
|
||||
<path d="M443.567,272.226C438.383,276.258 434.063,278.274 430.607,278.274C423.695,278.274 416.783,274.146 409.871,265.89L369.263,293.826C362.927,298.434 359.759,304.194 359.759,311.106L359.759,429.186L359.471,429.474C359.471,432.354 358.559,435.234 356.735,438.114C354.911,440.994 352.943,442.434 350.831,442.434L350.255,442.434L350.255,439.554L347.951,442.722C345.071,442.53 337.583,439.17 325.487,432.642L325.487,432.93C313.199,425.826 302.927,422.274 294.671,422.274C286.223,422.274 278.447,425.442 271.343,431.778C268.079,434.658 265.439,438.162 263.423,442.29C261.407,446.418 260.111,451.266 259.535,456.834C263.759,451.842 268.943,449.058 275.087,448.482C276.239,448.482 277.007,448.386 277.391,448.194L277.967,448.194C282.191,448.194 290.351,450.594 302.447,455.394C308.207,457.698 315.215,458.85 323.471,458.85C334.991,458.85 347.471,455.778 360.911,449.634C376.271,442.53 385.871,434.082 389.711,424.29C390.287,422.946 390.575,421.602 390.575,420.258L390.863,370.722L410.735,370.722L410.735,431.778L421.391,431.778L421.391,301.314C425.231,300.354 428.687,298.482 431.759,295.698C434.831,292.914 437.807,289.314 440.687,284.898C443.183,281.058 444.431,278.274 444.431,276.546L444.719,276.258C444.719,275.49 444.911,274.53 445.295,273.378L443.567,272.226ZM356.015,297.282C350.447,298.242 345.503,299.874 341.183,302.178C336.863,304.482 332.975,307.266 329.519,310.53C321.647,317.634 317.711,326.562 317.711,337.314L317.711,338.754L317.999,339.042L317.999,340.194C317.231,340.194 316.655,340.098 316.271,339.906L313.679,339.906C298.127,339.906 290.351,347.874 290.351,363.81C290.351,368.418 291.695,372.498 294.383,376.05C297.071,379.602 300.719,381.378 305.327,381.378L305.327,379.362L305.039,379.074L305.039,377.922L304.751,377.634C304.751,373.218 308.015,371.01 314.543,371.01L316.559,371.01L317.135,371.298L318.287,371.298L318.287,413.634C318.095,414.018 317.951,414.498 317.855,415.074C317.759,415.65 317.615,416.13 317.423,416.514C317.039,417.282 316.703,418.194 316.415,419.25C316.127,420.306 315.887,421.026 315.695,421.41L318.575,421.41L319.151,421.122L319.727,421.122L320.015,420.834C322.703,420.834 326.351,419.202 330.959,415.938C344.399,407.106 351.119,396.93 351.119,385.41L351.119,310.818C351.119,308.706 351.647,306.45 352.703,304.05C353.759,301.65 355.055,300.162 356.591,299.586L356.015,297.282ZM375.023,266.754C370.415,270.978 365.231,273.09 359.471,273.09C351.407,273.09 345.647,272.226 342.191,270.498L341.615,270.498L341.327,270.21C338.063,269.634 335.375,269.106 333.263,268.626C331.151,268.146 329.615,267.81 328.655,267.618L325.775,267.618C320.207,267.042 317.231,266.562 316.847,266.178L314.831,267.042C298.319,267.426 286.799,273.186 280.271,284.322C277.391,289.314 275.951,293.73 275.951,297.57L275.951,300.162C282.671,295.938 286.991,293.826 288.911,293.826L290.063,293.826L290.351,293.538C294.767,293.538 302.063,294.594 312.239,296.706C321.839,298.818 329.039,299.874 333.839,299.874L334.127,300.162L335.279,300.162C344.687,300.162 353.615,297.09 362.063,290.946C371.087,284.418 376.079,276.642 377.039,267.618L375.023,266.754ZM409.583,301.89C409.775,301.89 409.919,301.938 410.015,302.034C410.111,302.13 410.351,302.082 410.735,301.89L410.735,340.482L390.863,340.482L390.863,294.402C397.967,299.394 404.207,301.89 409.583,301.89Z" style="fill:rgb(31,34,41);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.0 KiB |
@@ -7,7 +7,7 @@
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <app_links/app_links_plugin_c_api.h>
|
||||
#include <just_audio_windows/just_audio_windows_plugin.h>
|
||||
#include <media_kit_libs_windows_audio/media_kit_libs_windows_audio_plugin_c_api.h>
|
||||
#include <screen_retriever/screen_retriever_plugin.h>
|
||||
#include <url_launcher_windows/url_launcher_windows.h>
|
||||
#include <window_manager/window_manager_plugin.h>
|
||||
@@ -15,8 +15,8 @@
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
AppLinksPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("AppLinksPluginCApi"));
|
||||
JustAudioWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("JustAudioWindowsPlugin"));
|
||||
MediaKitLibsWindowsAudioPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("MediaKitLibsWindowsAudioPluginCApi"));
|
||||
ScreenRetrieverPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("ScreenRetrieverPlugin"));
|
||||
UrlLauncherWindowsRegisterWithRegistrar(
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
app_links
|
||||
just_audio_windows
|
||||
media_kit_libs_windows_audio
|
||||
screen_retriever
|
||||
url_launcher_windows
|
||||
window_manager
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
media_kit_native_event_loop
|
||||
)
|
||||
|
||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||
|
||||
@@ -56,7 +56,7 @@ const IOS = () => (
|
||||
<path d="M318.7,268.7C318.5,232 335.1,204.3 368.7,183.9C349.9,157 321.5,142.2 284,139.3C248.5,136.5 209.7,160 195.5,160C180.5,160 146.1,140.3 119.1,140.3C63.3,141.2 4,184.8 4,273.5C4,299.7 8.8,326.767 18.4,354.7C31.2,391.4 77.4,481.4 125.6,479.9C150.8,479.3 168.6,462 201.4,462C233.2,462 249.7,479.9 277.8,479.9C326.4,479.2 368.2,397.4 380.4,360.6C315.2,329.9 318.7,270.6 318.7,268.7ZM262.1,104.5C289.4,72.1 286.9,42.6 286.1,32C262,33.4 234.1,48.4 218.2,66.9C200.7,86.7 190.4,111.2 192.6,138.8C218.7,140.8 242.5,127.4 262.1,104.5Z" />
|
||||
</g>
|
||||
</svg>
|
||||
<span className="pt-4 text-xl">iOS (Comming Soon)</span>
|
||||
<span className="pt-4 text-xl">iOS</span>
|
||||
</div>
|
||||
</a>
|
||||
);
|
||||
@@ -76,7 +76,7 @@ const Android = () => (
|
||||
<path d="M420.55,301.93C407.384,301.93 396.55,291.096 396.55,277.93C396.55,264.764 407.384,253.93 420.55,253.93C433.716,253.93 444.55,264.764 444.55,277.93C444.55,291.096 433.716,301.93 420.55,301.93M155.45,301.93C142.284,301.93 131.45,291.096 131.45,277.93C131.45,264.764 142.284,253.93 155.45,253.93C168.616,253.93 179.45,264.764 179.45,277.93C179.45,291.096 168.616,301.93 155.45,301.93M429.15,157.45L477.09,74.45C478.196,72.802 478.786,70.862 478.786,68.878C478.786,63.392 474.272,58.878 468.786,58.878C464.987,58.878 461.502,61.043 459.82,64.45L411.28,148.52C332.897,113.365 243.103,113.365 164.72,148.52L116.18,64.45C114.498,61.043 111.013,58.878 107.214,58.878C101.728,58.878 97.214,63.392 97.214,68.878C97.214,70.862 97.804,72.802 98.91,74.45L146.85,157.45C64.53,202.22 8.24,285.55 0,384L576,384C567.76,285.55 511.46,202.22 429.15,157.45" />
|
||||
</g>
|
||||
</svg>
|
||||
<span className="pt-4 text-xl">Android (Comming Soon)</span>
|
||||
<span className="pt-4 text-xl">Android</span>
|
||||
</div>
|
||||
</a>
|
||||
);
|
||||
@@ -119,7 +119,7 @@ const MacOS = () => (
|
||||
<path d="M318.7,268.7C318.5,232 335.1,204.3 368.7,183.9C349.9,157 321.5,142.2 284,139.3C248.5,136.5 209.7,160 195.5,160C180.5,160 146.1,140.3 119.1,140.3C63.3,141.2 4,184.8 4,273.5C4,299.7 8.8,326.767 18.4,354.7C31.2,391.4 77.4,481.4 125.6,479.9C150.8,479.3 168.6,462 201.4,462C233.2,462 249.7,479.9 277.8,479.9C326.4,479.2 368.2,397.4 380.4,360.6C315.2,329.9 318.7,270.6 318.7,268.7ZM262.1,104.5C289.4,72.1 286.9,42.6 286.1,32C262,33.4 234.1,48.4 218.2,66.9C200.7,86.7 190.4,111.2 192.6,138.8C218.7,140.8 242.5,127.4 262.1,104.5Z" />
|
||||
</g>
|
||||
</svg>
|
||||
<span className="pt-4 text-xl">macOS (Comming Soon)</span>
|
||||
<span className="pt-4 text-xl">macOS</span>
|
||||
</div>
|
||||
</a>
|
||||
);
|
||||
@@ -139,7 +139,7 @@ const Windows = () => (
|
||||
<path d="M0,93.7L183.6,68.4L183.6,245.8L0,245.8L0,93.7ZM0,418.3L183.6,443.6L183.6,268.4L0,268.4L0,418.3ZM203.8,446.3L448,480L448,268.4L203.8,268.4L203.8,446.3ZM203.8,65.7L203.8,245.8L448,245.8L448,32L203.8,65.7Z" />
|
||||
</g>
|
||||
</svg>
|
||||
<span className="pt-4 text-xl">Windows (Comming Soon)</span>
|
||||
<span className="pt-4 text-xl">Windows</span>
|
||||
</div>
|
||||
</a>
|
||||
);
|
||||
@@ -159,7 +159,7 @@ const Linux = () => (
|
||||
<path d="M220.8,123.3C221.8,123.8 222.6,125 223.8,125C224.9,125 226.6,124.6 226.7,123.5C226.9,122.1 224.8,121.2 223.5,120.6C221.8,119.9 219.6,119.6 218,120.5C217.6,120.7 217.2,121.2 217.4,121.6C217.7,122.9 219.7,122.7 220.8,123.3ZM198.9,125C200.1,125 200.9,123.8 201.9,123.3C203,122.7 205,122.9 205.4,121.7C205.6,121.3 205.2,120.8 204.8,120.6C203.2,119.7 201,120 199.3,120.7C198,121.3 195.9,122.2 196.1,123.6C196.2,124.6 197.9,125.1 198.9,125ZM420,403.8C416.4,399.8 414.7,392.2 412.8,384.1C411,376 408.9,367.3 402.3,361.7C401,360.6 399.7,359.6 398.3,358.8C397,358 395.6,357.3 394.2,356.8C403.4,329.5 399.8,302.3 390.5,277.7C379.1,247.6 359.2,221.3 344,203.3C326.9,181.8 310.3,161.4 310.6,131.3C311.1,85.4 315.7,0.1 234.8,0C132.4,-0.2 158,103.4 156.9,135.2C155.2,158.6 150.5,177 134.4,199.9C115.5,222.4 88.9,258.7 76.3,296.6C70.3,314.5 67.5,332.7 70.1,349.9C63.6,355.7 58.7,364.6 53.5,370.1C49.3,374.4 43.2,376 36.5,378.4C29.8,380.8 22.5,384.4 18,392.9C15.9,396.8 15.2,401 15.2,405.3C15.2,409.2 15.8,413.2 16.4,417.1C17.6,425.2 18.9,432.8 17.2,437.9C12,452.3 11.3,462.3 15,469.6C18.8,476.9 26.4,480.1 35.1,481.9C52.4,485.5 75.9,484.6 94.4,494.4C114.2,504.8 134.3,508.5 150.3,504.8C161.9,502.2 171.4,495.2 176.2,484.6C188.7,484.5 202.5,479.2 224.5,478C239.4,476.8 258.1,483.3 279.6,482.1C280.2,484.4 281,486.7 282.1,488.8L282.1,488.9C290.4,505.6 305.9,513.2 322.4,511.9C339,510.6 356.5,500.9 370.7,484C384.3,467.6 406.7,460.8 421.6,451.8C429,447.3 435,441.7 435.5,433.5C435.9,425.3 431.1,416.2 420,403.8ZM223.7,87.3C233.5,65.1 257.9,65.5 267.7,86.9C274.2,101.1 271.3,117.8 263.4,127.3C261.8,126.5 257.5,124.7 250.8,122.4C251.9,121.2 253.9,119.7 254.7,117.8C259.5,106 254.5,90.8 245.6,90.5C238.3,90 231.7,101.3 233.8,113.5C229.7,111.5 224.4,110 220.8,109.1C219.8,102.2 220.5,94.5 223.7,87.3ZM183,75.8C193.1,75.8 203.8,90 202.1,109.3C198.6,110.3 195,111.8 191.9,113.9C193.1,105 188.6,93.8 182.3,94.3C173.9,95 172.5,115.5 180.5,122.4C181.5,123.2 182.4,122.2 174.6,127.9C159,113.3 164.1,75.8 183,75.8ZM169.4,136.5C175.6,131.9 183,126.5 183.5,126C188.2,121.6 197,111.8 211.4,111.8C218.5,111.8 227,114.1 237.3,120.7C243.6,124.8 248.6,125.1 259.9,130C268.3,133.5 273.6,139.7 270.4,148.2C267.8,155.3 259.4,162.6 247.7,166.3C236.6,169.9 227.9,182.3 209.5,181.2C205.6,181 202.5,180.2 199.9,179.1C191.9,175.6 187.7,168.7 179.9,164.1C171.3,159.3 166.7,153.7 165.2,148.8C163.8,143.9 165.2,139.8 169.4,136.5ZM172.7,470.5C170,505.6 128.8,504.9 97.4,488.5C67.5,472.7 28.8,482 20.9,466.6C18.5,461.9 18.5,453.9 23.5,440.2L23.5,440C25.9,432.4 24.1,424 22.9,416.1C21.7,408.3 21.1,401.1 23.8,396.1C27.3,389.4 32.3,387 38.6,384.8C48.9,381.1 50.4,381.4 58.2,374.9C63.7,369.2 67.7,362 72.5,356.9C77.6,351.4 82.5,348.8 90.2,350C98.3,351.2 105.3,356.8 112.1,366L131.7,401.6C141.2,421.5 174.8,450 172.7,470.5ZM171.3,444.6C167.2,438 161.7,431 156.9,425C164,425 171.1,422.8 173.6,416.1C175.9,409.9 173.6,401.2 166.2,391.2C152.7,373 127.9,358.7 127.9,358.7C114.4,350.3 106.8,340 103.3,328.8C99.8,317.6 100.3,305.5 103,293.6C108.2,270.7 121.6,248.4 130.2,234.4C132.5,232.7 131,237.6 121.5,255.2C113,271.3 97.1,308.5 118.9,337.6C119.5,316.9 124.4,295.8 132.7,276.1C144.7,248.7 170,201.2 172,163.4C173.1,164.2 176.6,166.6 178.2,167.5C182.8,170.2 186.3,174.2 190.8,177.8C203.2,187.8 219.3,187 233.2,179C239.4,175.5 244.4,171.5 249.1,170C259,166.9 266.9,161.4 271.4,155C279.1,185.4 297.1,229.3 308.6,250.7C314.7,262.1 326.9,286.2 332.2,315.3C335.5,315.2 339.2,315.7 343.1,316.7C356.9,281 331.4,242.5 319.8,231.8C315.1,227.2 314.9,225.2 317.2,225.3C329.8,236.5 346.4,259 352.4,284.3C355.2,295.9 355.7,308 352.8,320C369.2,326.8 388.7,337.9 383.5,354.8C381.3,354.7 380.3,354.8 379.3,354.8C382.5,344.7 375.4,337.2 356.5,328.7C336.9,320.1 320.5,320.1 318.2,341.2C306.1,345.4 299.9,355.9 296.8,368.5C294,379.7 293.2,393.2 292.4,408.4C291.9,416.1 288.8,426.4 285.6,437.4C253.5,460.3 208.9,470.3 171.3,444.6ZM428.7,433.1C427.8,449.9 387.5,453 365.5,479.6C352.3,495.3 336.1,504 321.9,505.1C307.7,506.2 295.4,500.3 288.2,485.8C283.5,474.7 285.8,462.7 289.3,449.5C293,435.3 298.5,420.7 299.2,408.9C300,393.7 300.9,380.4 303.4,370.2C306,359.9 310,353 317.1,349.1C317.4,348.9 317.8,348.8 318.1,348.6C318.9,361.8 325.4,375.2 336.9,378.1C349.5,381.4 367.6,370.6 375.3,361.8C384.3,361.5 391,360.9 397.9,366.9C407.8,375.4 405,397.2 415,408.5C425.6,420.1 429,428 428.7,433.1ZM173.3,148.7C175.3,150.6 178,153.2 181.3,155.8C187.9,161 197.1,166.4 208.6,166.4C220.2,166.4 231.1,160.5 240.4,155.6C245.3,153 251.3,148.6 255.2,145.2C259.1,141.8 261.1,138.9 258.3,138.6C255.5,138.3 255.7,141.2 252.3,143.7C247.9,146.9 242.6,151.1 238.4,153.5C231,157.7 218.9,163.7 208.5,163.7C198.1,163.7 189.8,158.9 183.6,154C180.5,151.5 177.9,149 175.9,147.1C174.4,145.7 174,142.5 171.6,142.2C170.2,142.1 169.8,145.9 173.3,148.7Z" />
|
||||
</g>
|
||||
</svg>
|
||||
<span className="pt-4 text-xl">Linux (Comming Soon)</span>
|
||||
<span className="pt-4 text-xl">Linux</span>
|
||||
</div>
|
||||
</a>
|
||||
);
|
||||
|
||||
405
landing/app/get-started/desktop/page.tsx
Normal file
@@ -0,0 +1,405 @@
|
||||
import { ReactNode, useState } from "react";
|
||||
import type { Metadata } from "next";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
|
||||
import { generalMetadata } from "@/helpers/metadata";
|
||||
import GetStartedEntry from "@/components/getstartedentry";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
...generalMetadata,
|
||||
title: "FeedDeck - Support",
|
||||
};
|
||||
|
||||
export default function Support() {
|
||||
return (
|
||||
<main>
|
||||
<div className="container p-8 mx-auto">
|
||||
<div className="max-w-screen-xl mx-auto">
|
||||
<h1 className="text-4xl font-bold">Get Started - Desktop</h1>
|
||||
<Link href="/get-started/mobile">Go to mobile version</Link>
|
||||
|
||||
<GetStartedEntry
|
||||
title="Sign In / Sign Up"
|
||||
images={[
|
||||
"/get-started/desktop/1-1.webp",
|
||||
"/get-started/desktop/1-2.webp",
|
||||
"/get-started/desktop/1-3.webp",
|
||||
]}
|
||||
>
|
||||
<p className="pt-4">
|
||||
You can sign in to FeedDeck with your{" "}
|
||||
<span className="font-bold">Apple</span> account,{" "}
|
||||
<span className="font-bold">Google</span> account or with an{" "}
|
||||
<span className="font-bold">email address and password</span>.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
To sign in with an email address and password select{" "}
|
||||
<span className="font-bold">
|
||||
"Sign in with FeedDeck"
|
||||
</span>{" "}
|
||||
on the start parge. If you do not have an account yet, you can
|
||||
create one by clicking on{" "}
|
||||
<span className="font-bold">Sign Up</span> on the sign in page.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
If you sign up using your email address and password we send you
|
||||
an verification email to confirm your email address. Once the
|
||||
verification is done you are able to sign in using the provided
|
||||
email address and password.
|
||||
</p>
|
||||
</GetStartedEntry>
|
||||
|
||||
<GetStartedEntry
|
||||
title="Add a Column"
|
||||
images={[
|
||||
"/get-started/desktop/2-1.webp",
|
||||
"/get-started/desktop/2-2.webp",
|
||||
]}
|
||||
>
|
||||
<p className="pt-4">
|
||||
To add a new column click on the{" "}
|
||||
<span className="font-bold">plus icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="M440-440H200v-80h240v-240h80v240h240v80H520v240h-80v-240Z" />
|
||||
</svg>
|
||||
</span>) on the right side in the bottom bar.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
After you clicked on the plus icon a dialog will open. In this
|
||||
dialog you have to provide the name of the column and click on the
|
||||
{" "}
|
||||
<span className="font-bold">"Create Column"</span>{" "}
|
||||
button to create the column.
|
||||
</p>
|
||||
</GetStartedEntry>
|
||||
|
||||
<GetStartedEntry
|
||||
title="Manage Columns"
|
||||
images={[
|
||||
"/get-started/desktop/3-1.webp",
|
||||
]}
|
||||
>
|
||||
<p className="pt-4">
|
||||
To adjust the name or position of a column or to delete a column
|
||||
click on the <span className="font-bold">settings icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="m370-80-16-128q-13-5-24.5-12T307-235l-119 50L78-375l103-78q-1-7-1-13.5v-27q0-6.5 1-13.5L78-585l110-190 119 50q11-8 23-15t24-12l16-128h220l16 128q13 5 24.5 12t22.5 15l119-50 110 190-103 78q1 7 1 13.5v27q0 6.5-2 13.5l103 78-110 190-118-50q-11 8-23 15t-24 12L590-80H370Zm70-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z" />
|
||||
</svg>
|
||||
</span>) on the right side next to the column name.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
Adjust the name of the column in the input field and click on the
|
||||
{" "}
|
||||
<span className="font-bold">save icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="M840-680v480q0 33-23.5 56.5T760-120H200q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h480l160 160Zm-80 34L646-760H200v560h560v-446ZM480-240q50 0 85-35t35-85q0-50-35-85t-85-35q-50 0-85 35t-35 85q0 50 35 85t85 35ZM240-560h360v-160H240v160Zm-40-86v446-560 114Z" />
|
||||
</svg>
|
||||
</span>) to change the name of the column.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
To adjust the position of a column use the arrow keys on the left
|
||||
and right side on the bottom of the column settings.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
To delete a column click on the{" "}
|
||||
<span className="font-bold">trash icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="M280-120q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Zm400-600H280v520h400v-520ZM360-280h80v-360h-80v360Zm160 0h80v-360h-80v360ZM280-720v520-520Z" />
|
||||
</svg>
|
||||
</span>) in the middle on the bottom of the column settings.
|
||||
</p>
|
||||
</GetStartedEntry>
|
||||
|
||||
<GetStartedEntry
|
||||
title="Add a Source"
|
||||
images={[
|
||||
"/get-started/desktop/4-1.webp",
|
||||
"/get-started/desktop/4-2.webp",
|
||||
"/get-started/desktop/4-3.webp",
|
||||
]}
|
||||
>
|
||||
<p className="pt-4">
|
||||
To add a new source click on the{" "}
|
||||
<span className="font-bold">settings icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="m370-80-16-128q-13-5-24.5-12T307-235l-119 50L78-375l103-78q-1-7-1-13.5v-27q0-6.5 1-13.5L78-585l110-190 119 50q11-8 23-15t24-12l16-128h220l16 128q13 5 24.5 12t22.5 15l119-50 110 190-103 78q1 7 1 13.5v27q0 6.5-2 13.5l103 78-110 190-118-50q-11 8-23 15t-24 12L590-80H370Zm70-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z" />
|
||||
</svg>
|
||||
</span>) on the right side next to the column name. When the
|
||||
settings menu is opened click on the{" "}
|
||||
<span className="font-bold">"Add Source"</span>{" "}
|
||||
button to add a new source to the column.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
Select the type of the source you want to add, e.g. RSS, Podcast,
|
||||
YouTube or Mastodon and provide the required data in the next
|
||||
step. Once you have provided all the required data click on the
|
||||
{" "}
|
||||
<span className="font-bold">"Add Source"</span>{" "}
|
||||
button to add the source to the column. In the following you find
|
||||
some examples for some of the sources:
|
||||
</p>
|
||||
<div className="pl-8 pt-4 break-all">
|
||||
<ul className="list-disc">
|
||||
<li>
|
||||
<span className="font-bold">RSS:</span>{" "}
|
||||
https://www.tagesschau.de/xml/rss2/
|
||||
</li>
|
||||
<li>
|
||||
<span className="font-bold">Podcast:</span>{" "}
|
||||
https://kubernetespodcast.com/feeds/audio.xml
|
||||
</li>
|
||||
<li>
|
||||
<span className="font-bold">Podcast:</span>{" "}
|
||||
https://www.youtube.com/user/tagesschau
|
||||
</li>
|
||||
<li>
|
||||
<span className="font-bold">Mastodon:</span>{" "}
|
||||
@ricoberger@hachyderm.io
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</GetStartedEntry>
|
||||
|
||||
<GetStartedEntry
|
||||
title="Manage Sources"
|
||||
images={[
|
||||
"/get-started/desktop/5-1.webp",
|
||||
]}
|
||||
>
|
||||
<p className="pt-4">
|
||||
To manage the sources for a column click on the{" "}
|
||||
<span className="font-bold">settings icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="m370-80-16-128q-13-5-24.5-12T307-235l-119 50L78-375l103-78q-1-7-1-13.5v-27q0-6.5 1-13.5L78-585l110-190 119 50q11-8 23-15t24-12l16-128h220l16 128q13 5 24.5 12t22.5 15l119-50 110 190-103 78q1 7 1 13.5v27q0 6.5-2 13.5l103 78-110 190-118-50q-11 8-23 15t-24 12L590-80H370Zm70-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z" />
|
||||
</svg>
|
||||
</span>) on the right side next to the column name.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
You can delete a source by clicking on the{" "}
|
||||
<span className="font-bold">trash icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="M280-120q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Zm400-600H280v520h400v-520ZM360-280h80v-360h-80v360Zm160 0h80v-360h-80v360ZM280-720v520-520Z" />
|
||||
</svg>
|
||||
</span>) on the right side of the source name.
|
||||
</p>
|
||||
</GetStartedEntry>
|
||||
|
||||
<GetStartedEntry
|
||||
title="Filter Items"
|
||||
images={[
|
||||
"/get-started/desktop/6-1.webp",
|
||||
]}
|
||||
>
|
||||
<p className="pt-4">
|
||||
You can filter items by searching for the title and content of an
|
||||
item or by filtering by read, unread or bookmarked items. You can
|
||||
only show items related to a single source.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
To search for an item with a specifc title or content provide your
|
||||
search term in the search input field and press{" "}
|
||||
<span className="font-bold">Enter</span>.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
To only show read, unread or bookmarked items, click on the{" "}
|
||||
<span className="font-bold">filter icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="M400-240v-80h160v80H400ZM240-440v-80h480v80H240ZM120-640v-80h720v80H120Z" />
|
||||
</svg>
|
||||
</span>) next to the search input field and select the
|
||||
corresponding option.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
To only show items related to a single source select the source
|
||||
below the search input field. To show all items click again on the
|
||||
selected source.
|
||||
</p>
|
||||
</GetStartedEntry>
|
||||
|
||||
<GetStartedEntry
|
||||
title="Mark Items as Read and Bookmark Items"
|
||||
images={[
|
||||
"/get-started/desktop/7-1.webp",
|
||||
"/get-started/desktop/7-2.webp",
|
||||
]}
|
||||
>
|
||||
<p className="pt-4">
|
||||
To mark an item as{" "}
|
||||
<span className="font-bold">read / unread</span>{" "}
|
||||
click a bit longer on the item and select{" "}
|
||||
<span className="font-bold">"Mark as Read"</span> /{" "}
|
||||
<span className="font-bold">"Mark as Unread"</span>{" "}
|
||||
from the menu.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
To bookmark an item click a bit longer on the item and select{" "}
|
||||
<span className="font-bold">"Add Bookmark"</span>{" "}
|
||||
from the menu.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
When you click on an item the details view for the selected item
|
||||
is opened and the item will be marked as read automatically. You
|
||||
can then use the icons in the top right corner in the{" "}
|
||||
<span className="font-bold">details view</span>{" "}
|
||||
to mark an items as read / unread or to add it to your bookmarks.
|
||||
</p>
|
||||
</GetStartedEntry>
|
||||
|
||||
<GetStartedEntry
|
||||
title="Manage Decks"
|
||||
images={[
|
||||
"/get-started/desktop/8-1.webp",
|
||||
"/get-started/desktop/8-2.webp",
|
||||
]}
|
||||
>
|
||||
<p className="pt-4">
|
||||
To manage your decks click on the{" "}
|
||||
<span className="font-bold">settings icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="m370-80-16-128q-13-5-24.5-12T307-235l-119 50L78-375l103-78q-1-7-1-13.5v-27q0-6.5 1-13.5L78-585l110-190 119 50q11-8 23-15t24-12l16-128h220l16 128q13 5 24.5 12t22.5 15l119-50 110 190-103 78q1 7 1 13.5v27q0 6.5-2 13.5l103 78-110 190-118-50q-11 8-23 15t-24 12L590-80H370Zm70-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z" />
|
||||
</svg>
|
||||
</span>) on the right side in the bottom bar. This will open the
|
||||
settings menu where you can select the deck you want to view and
|
||||
where you can manage your decks.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
To add, edit or delete decks click on the{" "}
|
||||
<span className="font-bold">edit icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="M200-200h56l345-345-56-56-345 345v56Zm572-403L602-771l56-56q23-23 56.5-23t56.5 23l56 56q23 23 24 55.5T829-660l-57 57Zm-58 59L290-120H120v-170l424-424 170 170Zm-141-29-28-28 56 56-28-28Z" />
|
||||
</svg>
|
||||
</span>) on the right side of the decks section.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
To add a new deck use the last input field in the decks section.
|
||||
After you have provided a name click on the{" "}
|
||||
<span className="font-bold">plus icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="M440-440H200v-80h240v-240h80v240h240v80H520v240h-80v-240Z" />
|
||||
</svg>
|
||||
</span>) to add a new deck.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
To adjust the name of a deck use the corresponding input field and
|
||||
click the <span className="font-bold">save icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="M840-680v480q0 33-23.5 56.5T760-120H200q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h480l160 160Zm-80 34L646-760H200v560h560v-446ZM480-240q50 0 85-35t35-85q0-50-35-85t-85-35q-50 0-85 35t-35 85q0 50 35 85t85 35ZM240-560h360v-160H240v160Zm-40-86v446-560 114Z" />
|
||||
</svg>
|
||||
</span>) to save the changes.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
To delete a deck click on the{" "}
|
||||
<span className="font-bold">trash icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="M280-120q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Zm400-600H280v520h400v-520ZM360-280h80v-360h-80v360Zm160 0h80v-360h-80v360ZM280-720v520-520Z" />
|
||||
</svg>
|
||||
</span>) next to the deck name.
|
||||
</p>
|
||||
</GetStartedEntry>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
const Entry = (
|
||||
{ title, images, children }: {
|
||||
title: string;
|
||||
images: string[];
|
||||
children: ReactNode;
|
||||
},
|
||||
) => {
|
||||
return (
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mt-16">
|
||||
<div>
|
||||
<div className="h-full flex items-center">
|
||||
<div>
|
||||
<h2 className="text-xl font-bold">{title}</h2>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<div className="h-full flex items-center justify-center">
|
||||
<div className="p-2 bg-secondary rounded-lg">
|
||||
<Image
|
||||
src={images[0]}
|
||||
width={0}
|
||||
height={0}
|
||||
style={{ width: "100%", height: "auto" }}
|
||||
className="object-cover"
|
||||
alt="Feature"
|
||||
loading="eager"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
412
landing/app/get-started/mobile/page.tsx
Normal file
@@ -0,0 +1,412 @@
|
||||
import { ReactNode } from "react";
|
||||
import type { Metadata } from "next";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
|
||||
import { generalMetadata } from "@/helpers/metadata";
|
||||
import GetStartedEntry from "@/components/getstartedentry";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
...generalMetadata,
|
||||
title: "FeedDeck - Support",
|
||||
};
|
||||
|
||||
export default function Support() {
|
||||
return (
|
||||
<main>
|
||||
<div className="container p-8 mx-auto">
|
||||
<div className="max-w-screen-xl mx-auto">
|
||||
<h1 className="text-4xl font-bold">Get Started - Mobile</h1>
|
||||
<Link href="/get-started/desktop">Go to desktop version</Link>
|
||||
|
||||
<GetStartedEntry
|
||||
title="Sign In / Sign Up"
|
||||
images={[
|
||||
"/get-started/mobile/1-1.webp",
|
||||
"/get-started/mobile/1-2.webp",
|
||||
"/get-started/mobile/1-3.webp",
|
||||
]}
|
||||
isMobile={true}
|
||||
>
|
||||
<p className="pt-4">
|
||||
You can sign in to FeedDeck with your{" "}
|
||||
<span className="font-bold">Apple</span> account,{" "}
|
||||
<span className="font-bold">Google</span> account or with an{" "}
|
||||
<span className="font-bold">email address and password</span>.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
To sign in with an email address and password select{" "}
|
||||
<span className="font-bold">
|
||||
"Sign in with FeedDeck"
|
||||
</span>{" "}
|
||||
on the start parge. If you do not have an account yet, you can
|
||||
create one by clicking on{" "}
|
||||
<span className="font-bold">Sign Up</span> on the sign in page.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
If you sign up using your email address and password we send you
|
||||
an verification email to confirm your email address. Once the
|
||||
verification is done you are able to sign in using the provided
|
||||
email address and password.
|
||||
</p>
|
||||
</GetStartedEntry>
|
||||
|
||||
<GetStartedEntry
|
||||
title="Add a Column"
|
||||
images={[
|
||||
"/get-started/mobile/2-1.webp",
|
||||
"/get-started/mobile/2-2.webp",
|
||||
]}
|
||||
isMobile={true}
|
||||
>
|
||||
<p className="pt-4">
|
||||
To add a new column click on the{" "}
|
||||
<span className="font-bold">plus icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="M440-440H200v-80h240v-240h80v240h240v80H520v240h-80v-240Z" />
|
||||
</svg>
|
||||
</span>) in the sidebar on the left side.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
After you clicked on the plus icon a dialog will open. In this
|
||||
dialog you have to provide the name of the column and click on the
|
||||
{" "}
|
||||
<span className="font-bold">"Create Column"</span>{" "}
|
||||
button to create the column.
|
||||
</p>
|
||||
</GetStartedEntry>
|
||||
|
||||
<GetStartedEntry
|
||||
title="Manage Columns"
|
||||
images={[
|
||||
"/get-started/mobile/3-1.webp",
|
||||
]}
|
||||
isMobile={true}
|
||||
>
|
||||
<p className="pt-4">
|
||||
To adjust the name or position of a column or to delete a column
|
||||
click on the <span className="font-bold">settings icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="m370-80-16-128q-13-5-24.5-12T307-235l-119 50L78-375l103-78q-1-7-1-13.5v-27q0-6.5 1-13.5L78-585l110-190 119 50q11-8 23-15t24-12l16-128h220l16 128q13 5 24.5 12t22.5 15l119-50 110 190-103 78q1 7 1 13.5v27q0 6.5-2 13.5l103 78-110 190-118-50q-11 8-23 15t-24 12L590-80H370Zm70-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z" />
|
||||
</svg>
|
||||
</span>) on the right side next to the column name.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
Adjust the name of the column in the input field and click on the
|
||||
{" "}
|
||||
<span className="font-bold">save icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="M840-680v480q0 33-23.5 56.5T760-120H200q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h480l160 160Zm-80 34L646-760H200v560h560v-446ZM480-240q50 0 85-35t35-85q0-50-35-85t-85-35q-50 0-85 35t-35 85q0 50 35 85t85 35ZM240-560h360v-160H240v160Zm-40-86v446-560 114Z" />
|
||||
</svg>
|
||||
</span>) to change the name of the column.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
To adjust the position of a column use the arrow keys on the left
|
||||
and right side on the bottom of the column settings.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
To delete a column click on the{" "}
|
||||
<span className="font-bold">trash icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="M280-120q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Zm400-600H280v520h400v-520ZM360-280h80v-360h-80v360Zm160 0h80v-360h-80v360ZM280-720v520-520Z" />
|
||||
</svg>
|
||||
</span>) in the middle on the bottom of the column settings.
|
||||
</p>
|
||||
</GetStartedEntry>
|
||||
|
||||
<GetStartedEntry
|
||||
title="Add a Source"
|
||||
images={[
|
||||
"/get-started/mobile/4-1.webp",
|
||||
"/get-started/mobile/4-2.webp",
|
||||
"/get-started/mobile/4-3.webp",
|
||||
]}
|
||||
isMobile={true}
|
||||
>
|
||||
<p className="pt-4">
|
||||
To add a new source click on the{" "}
|
||||
<span className="font-bold">settings icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="m370-80-16-128q-13-5-24.5-12T307-235l-119 50L78-375l103-78q-1-7-1-13.5v-27q0-6.5 1-13.5L78-585l110-190 119 50q11-8 23-15t24-12l16-128h220l16 128q13 5 24.5 12t22.5 15l119-50 110 190-103 78q1 7 1 13.5v27q0 6.5-2 13.5l103 78-110 190-118-50q-11 8-23 15t-24 12L590-80H370Zm70-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z" />
|
||||
</svg>
|
||||
</span>) on the right side next to the column name. When the
|
||||
settings menu is opened click on the{" "}
|
||||
<span className="font-bold">"Add Source"</span>{" "}
|
||||
button to add a new source to the column.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
Select the type of the source you want to add, e.g. RSS, Podcast,
|
||||
YouTube or Mastodon and provide the required data in the next
|
||||
step. Once you have provided all the required data click on the
|
||||
{" "}
|
||||
<span className="font-bold">"Add Source"</span>{" "}
|
||||
button to add the source to the column. In the following you find
|
||||
some examples for some of the sources:
|
||||
</p>
|
||||
|
||||
<div className="pl-8 pt-4 break-all">
|
||||
<ul className="list-disc">
|
||||
<li>
|
||||
<span className="font-bold">RSS:</span>{" "}
|
||||
https://www.tagesschau.de/xml/rss2/
|
||||
</li>
|
||||
<li>
|
||||
<span className="font-bold">Podcast:</span>{" "}
|
||||
https://kubernetespodcast.com/feeds/audio.xml
|
||||
</li>
|
||||
<li>
|
||||
<span className="font-bold">Podcast:</span>{" "}
|
||||
https://www.youtube.com/user/tagesschau
|
||||
</li>
|
||||
<li>
|
||||
<span className="font-bold">Mastodon:</span>{" "}
|
||||
@ricoberger@hachyderm.io
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</GetStartedEntry>
|
||||
|
||||
<GetStartedEntry
|
||||
title="Manage Sources"
|
||||
images={[
|
||||
"/get-started/mobile/5-1.webp",
|
||||
]}
|
||||
isMobile={true}
|
||||
>
|
||||
<p className="pt-4">
|
||||
To manage the sources for a column click on the{" "}
|
||||
<span className="font-bold">settings icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="m370-80-16-128q-13-5-24.5-12T307-235l-119 50L78-375l103-78q-1-7-1-13.5v-27q0-6.5 1-13.5L78-585l110-190 119 50q11-8 23-15t24-12l16-128h220l16 128q13 5 24.5 12t22.5 15l119-50 110 190-103 78q1 7 1 13.5v27q0 6.5-2 13.5l103 78-110 190-118-50q-11 8-23 15t-24 12L590-80H370Zm70-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z" />
|
||||
</svg>
|
||||
</span>) on the right side next to the column name.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
You can delete a source by clicking on the{" "}
|
||||
<span className="font-bold">trash icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="M280-120q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Zm400-600H280v520h400v-520ZM360-280h80v-360h-80v360Zm160 0h80v-360h-80v360ZM280-720v520-520Z" />
|
||||
</svg>
|
||||
</span>) on the right side of the source name.
|
||||
</p>
|
||||
</GetStartedEntry>
|
||||
|
||||
<GetStartedEntry
|
||||
title="Filter Items"
|
||||
images={[
|
||||
"/get-started/mobile/6-1.webp",
|
||||
]}
|
||||
isMobile={true}
|
||||
>
|
||||
<p className="pt-4">
|
||||
You can filter items by searching for the title and content of an
|
||||
item or by filtering by read, unread or bookmarked items. You can
|
||||
only show items related to a single source.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
To search for an item with a specifc title or content provide your
|
||||
search term in the search input field and press{" "}
|
||||
<span className="font-bold">Enter</span>.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
To only show read, unread or bookmarked items, click on the{" "}
|
||||
<span className="font-bold">filter icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="M400-240v-80h160v80H400ZM240-440v-80h480v80H240ZM120-640v-80h720v80H120Z" />
|
||||
</svg>
|
||||
</span>) next to the search input field and select the
|
||||
corresponding option.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
To only show items related to a single source select the source
|
||||
below the search input field. To show all items click again on the
|
||||
selected source.
|
||||
</p>
|
||||
</GetStartedEntry>
|
||||
|
||||
<GetStartedEntry
|
||||
title="Mark Items as Read and Bookmark Items"
|
||||
images={[
|
||||
"/get-started/mobile/7-1.webp",
|
||||
"/get-started/mobile/7-2.webp",
|
||||
]}
|
||||
isMobile={true}
|
||||
>
|
||||
<p className="pt-4">
|
||||
To mark an item as{" "}
|
||||
<span className="font-bold">read / unread</span>{" "}
|
||||
click a bit longer on the item and select{" "}
|
||||
<span className="font-bold">"Mark as Read"</span> /{" "}
|
||||
<span className="font-bold">"Mark as Unread"</span>{" "}
|
||||
from the menu.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
To bookmark an item click a bit longer on the item and select{" "}
|
||||
<span className="font-bold">"Add Bookmark"</span>{" "}
|
||||
from the menu.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
When you click on an item the details view for the selected item
|
||||
is opened and the item will be marked as read automatically. You
|
||||
can then use the icons in the top right corner in the{" "}
|
||||
<span className="font-bold">details view</span>{" "}
|
||||
to mark an items as read / unread or to add it to your bookmarks.
|
||||
</p>
|
||||
</GetStartedEntry>
|
||||
|
||||
<GetStartedEntry
|
||||
title="Manage Decks"
|
||||
images={[
|
||||
"/get-started/mobile/8-1.webp",
|
||||
"/get-started/mobile/8-2.webp",
|
||||
]}
|
||||
isMobile={true}
|
||||
>
|
||||
<p className="pt-4">
|
||||
To manage your decks click on the{" "}
|
||||
<span className="font-bold">settings icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="m370-80-16-128q-13-5-24.5-12T307-235l-119 50L78-375l103-78q-1-7-1-13.5v-27q0-6.5 1-13.5L78-585l110-190 119 50q11-8 23-15t24-12l16-128h220l16 128q13 5 24.5 12t22.5 15l119-50 110 190-103 78q1 7 1 13.5v27q0 6.5-2 13.5l103 78-110 190-118-50q-11 8-23 15t-24 12L590-80H370Zm70-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z" />
|
||||
</svg>
|
||||
</span>) in the sidebar on the left side. This will open the
|
||||
settings menu where you can select the deck you want to view and
|
||||
where you can manage your decks.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
To add, edit or delete decks click on the{" "}
|
||||
<span className="font-bold">edit icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="M200-200h56l345-345-56-56-345 345v56Zm572-403L602-771l56-56q23-23 56.5-23t56.5 23l56 56q23 23 24 55.5T829-660l-57 57Zm-58 59L290-120H120v-170l424-424 170 170Zm-141-29-28-28 56 56-28-28Z" />
|
||||
</svg>
|
||||
</span>) on the right side of the decks section.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
To add a new deck use the last input field in the decks section.
|
||||
After you have provided a name click on the{" "}
|
||||
<span className="font-bold">plus icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="M440-440H200v-80h240v-240h80v240h240v80H520v240h-80v-240Z" />
|
||||
</svg>
|
||||
</span>) to add a new deck.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
To adjust the name of a deck use the corresponding input field and
|
||||
click the <span className="font-bold">save icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="M840-680v480q0 33-23.5 56.5T760-120H200q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h480l160 160Zm-80 34L646-760H200v560h560v-446ZM480-240q50 0 85-35t35-85q0-50-35-85t-85-35q-50 0-85 35t-35 85q0 50 35 85t85 35ZM240-560h360v-160H240v160Zm-40-86v446-560 114Z" />
|
||||
</svg>
|
||||
</span>) to save the changes.
|
||||
</p>
|
||||
<p className="pt-4">
|
||||
To delete a deck click on the{" "}
|
||||
<span className="font-bold">trash icon</span>{" "}
|
||||
(<span className="font-bold inline-flex items-baseline">
|
||||
<svg
|
||||
className="w-4 h-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
>
|
||||
<path d="M280-120q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Zm400-600H280v520h400v-520ZM360-280h80v-360h-80v360Zm160 0h80v-360h-80v360ZM280-720v520-520Z" />
|
||||
</svg>
|
||||
</span>) next to the deck name.
|
||||
</p>
|
||||
</GetStartedEntry>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
const Entry = (
|
||||
{ title, image, children }: {
|
||||
title: string;
|
||||
image: string;
|
||||
children: ReactNode;
|
||||
},
|
||||
) => (
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mt-16">
|
||||
<div>
|
||||
<div className="h-full flex items-center">
|
||||
<div>
|
||||
<h2 className="text-xl font-bold">{title}</h2>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<div className="h-full flex items-center justify-center">
|
||||
<div className="p-2 bg-secondary rounded-lg">
|
||||
<Image
|
||||
src={image}
|
||||
width={0}
|
||||
height={0}
|
||||
style={{ width: "100%", height: "auto" }}
|
||||
className="object-cover"
|
||||
alt="Feature"
|
||||
loading="eager"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -65,8 +65,9 @@ export default function Pricing() {
|
||||
<div className="flex justify-center items-baseline my-8">
|
||||
<span className="mr-2 text-5xl font-extrabold">5€</span>
|
||||
<span className="text-gray-400">
|
||||
/month
|
||||
/ month{" "}
|
||||
</span>
|
||||
<span className="text-xl text-gray-400">*</span>
|
||||
</div>
|
||||
|
||||
<ul role="list" className="mb-8 space-y-4 text-left">
|
||||
@@ -129,6 +130,10 @@ export default function Pricing() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="py-8 px-4 mx-auto max-w-screen-xl lg:py-16 lg:px-6">
|
||||
* The price for a premium account buyed via in-app purchase on iOS,
|
||||
macOS or Android can be different due to the fees of the app stores.
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -142,9 +147,9 @@ const Feature = ({ children }: { children: ReactNode }) => (
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
fillRule="evenodd"
|
||||
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
|
||||
clip-rule="evenodd"
|
||||
clipRule="evenodd"
|
||||
>
|
||||
</path>
|
||||
</svg>
|
||||
|
||||
@@ -84,23 +84,101 @@ export default function TermsAndConditions() {
|
||||
</p>
|
||||
<p className="py-4">
|
||||
At some point, we may wish to update the app. The app is currently
|
||||
available on iOS – the requirements for the system(and for any
|
||||
additional systems we decide to extend the availability of the app
|
||||
to) may change, and you'll need to download the updates if you
|
||||
want to keep using the app. Rico Berger does not promise that it
|
||||
will always update the app so that it is relevant to you and/or
|
||||
works with the iOS version that you have installed on your device.
|
||||
However, you promise to always accept updates to the application
|
||||
when offered to you, We may also wish to stop providing the app, and
|
||||
may terminate use of it at any time without giving notice of
|
||||
termination to you. Unless we tell you otherwise, upon any
|
||||
available on Android, iOS, macOS, Windows and Linux – the
|
||||
requirements for the system (and for any additional systems we
|
||||
decide to extend the availability of the app to) may change, and
|
||||
you'll need to download the updates if you want to keep using
|
||||
the app. Rico Berger does not promise that it will always update the
|
||||
app so that it is relevant to you and/or works with the Android,
|
||||
iOS, macOS, Windows and Linux version that you have installed on
|
||||
your device. However, you promise to always accept updates to the
|
||||
application when offered to you, We may also wish to stop providing
|
||||
the app, and may terminate use of it at any time without giving
|
||||
notice of termination to you. Unless we tell you otherwise, upon any
|
||||
termination, (a) the rights and licenses granted to you in these
|
||||
terms will end; (b) you must stop using the app, and (if needed)
|
||||
delete it from your device.
|
||||
</p>
|
||||
<p className="py-4">
|
||||
<h2 className="text-xl font-bold">
|
||||
Changes to This Terms and Conditions
|
||||
Accessing and Download the Application from an App Store
|
||||
</h2>
|
||||
</p>
|
||||
<p className="py-4">
|
||||
The following applies to any App accessed through or downloaded from
|
||||
an App Store:
|
||||
</p>
|
||||
<p className="pl-8 py-4">
|
||||
<ul className="list-disc">
|
||||
<li>
|
||||
(a) You acknowledge and agree that (i) the Terms are concluded
|
||||
between you and Rico Berger only, and not Apple, Google or
|
||||
Microsoft, and (ii) Rico Berger, not Apple, Google or Microsoft,
|
||||
is solely responsible for the App and content thereof. Your use
|
||||
of the App must comply with the applicable App Store's
|
||||
terms of service or usage rules.
|
||||
</li>
|
||||
<li>
|
||||
(b) You acknowledge that the App Store has no obligation
|
||||
whatsoever to furnish any maintenance and support services with
|
||||
respect to the App.
|
||||
</li>
|
||||
<li>
|
||||
(c) In the event of any failure of the App to conform to any
|
||||
applicable warranty, you may notify the App Store, and the App
|
||||
Store will refund the purchase price for the App to you and to
|
||||
the maximum extent permitted by applicable law, neither Apple,
|
||||
Google or Microsoft will have any other warranty obligation
|
||||
whatsoever with respect to the App. As between Rico Berger and
|
||||
the App Store, any other claims, losses, liabilities, damages,
|
||||
costs or expenses attributable to any failure to conform to any
|
||||
warranty will be the sole responsibility of Rico Berger.
|
||||
</li>
|
||||
<li>
|
||||
(d) You and Rico Berger acknowledge that, as between Rico Berger
|
||||
and the App Store, the App Store is not responsible for
|
||||
addressing any claims you have or any claims of any third party
|
||||
relating to the App or your possession and use of the App,
|
||||
including, but not limited to: (i) product liability claims;
|
||||
(ii) any claim that the App fails to conform to any applicable
|
||||
legal or regulatory requirement; and (iii) claims arising under
|
||||
consumer protection or similar legislation.
|
||||
</li>
|
||||
<li>
|
||||
(e) You and Rico Berger acknowledge that, in the event of any
|
||||
third-party claim that the App or your possession and use of
|
||||
that App infringes that third party's intellectual property
|
||||
rights, as between Rico Berger and App Store, Rico Berger, not
|
||||
the App Store, will be solely responsible for the investigation,
|
||||
defense, settlement and discharge of any such intellectual
|
||||
property infringement claim to the extent required by the Terms.
|
||||
</li>
|
||||
<li>
|
||||
(f) You and Rico Berger acknowledge and agree that (i) Apple and
|
||||
Apple's subsidiaries, are third-party beneficiaries of the
|
||||
Terms as related to your license of the App from the Apple App
|
||||
Store, (ii) Google and Google's subsidiaries, are
|
||||
third-party beneficiaries of the Terms as related to your
|
||||
license of the App from the Android market or Google Play App
|
||||
Stores, and (iii) Microsoft and its subsidiaries are
|
||||
third-parties beneficiaries of the Terms as related to your
|
||||
license of the App from the Windows Store; and that, upon your
|
||||
acceptance of the terms and conditions of the Terms, Apple,
|
||||
Google, or Microsoft, as applicable, will have the right (and
|
||||
will be deemed to have accepted the right) to enforce the Terms
|
||||
as related to your license of the App against you as a
|
||||
third-party beneficiary thereof.
|
||||
</li>
|
||||
<li>
|
||||
(g) Without limiting any other terms of the Terms, you must
|
||||
comply with all applicable third-party terms of agreement when
|
||||
using the App.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p className="py-4">
|
||||
<h2 className="text-xl font-bold">
|
||||
Changes to this Terms and Conditions
|
||||
</h2>
|
||||
</p>
|
||||
<p className="py-4">
|
||||
@@ -110,7 +188,7 @@ export default function TermsAndConditions() {
|
||||
this page.
|
||||
</p>
|
||||
<p className="py-4">
|
||||
These terms and conditions are effective as of 2023-06-22
|
||||
These terms and conditions are effective as of 2023-10-18
|
||||
</p>
|
||||
<p className="py-4">
|
||||
<h2 className="text-xl font-bold">Contact Us</h2>
|
||||
|
||||
61
landing/components/getstartedentry.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
"use client";
|
||||
|
||||
import { ReactNode, useState } from "react";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
|
||||
export default function GetStartedEntry({ title, images, isMobile, children }: {
|
||||
title: string;
|
||||
images: string[];
|
||||
isMobile?: boolean;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
const [index, setIndex] = useState<number>(0);
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mt-16">
|
||||
<div>
|
||||
<div className="h-full flex items-center">
|
||||
<div>
|
||||
<h2 className="text-xl font-bold">{title}</h2>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<div className="h-full flex items-center justify-center">
|
||||
<div className="relative p-2 bg-secondary rounded-lg">
|
||||
<Link
|
||||
href={images[index]}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
src={images[index]}
|
||||
width={0}
|
||||
height={0}
|
||||
style={isMobile
|
||||
? { width: "auto", height: "75vh" }
|
||||
: { width: "100%", height: "auto" }}
|
||||
className="object-cover"
|
||||
alt="Image"
|
||||
loading="eager"
|
||||
/>
|
||||
</Link>
|
||||
<div className="absolute flex space-x-3 -translate-x-1/2 bottom-5 left-1/2">
|
||||
{images.map((_, index) => (
|
||||
<button
|
||||
key={index}
|
||||
type="button"
|
||||
className="w-4 h-4 bg-secondary rounded-full"
|
||||
onClick={() => setIndex(index)}
|
||||
>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -2,12 +2,13 @@ type TPlatform = "ios" | "android";
|
||||
type TOS = "ios" | "android" | "macos" | "windows" | "linux";
|
||||
|
||||
export const downloads = {
|
||||
"ios": "https://app.feeddeck.app",
|
||||
"android": "https://app.feeddeck.app",
|
||||
"ios": "https://apps.apple.com/us/app/feeddeck/id6451055362",
|
||||
"android":
|
||||
"https://play.google.com/store/apps/details?id=app.feeddeck.feeddeck",
|
||||
"web": "https://app.feeddeck.app",
|
||||
"macos": "https://app.feeddeck.app",
|
||||
"windows": "https://app.feeddeck.app",
|
||||
"linux": "https://app.feeddeck.app",
|
||||
"macos": "https://apps.apple.com/us/app/feeddeck/id6451055362",
|
||||
"windows": "https://www.microsoft.com/store/apps/9NPHPGRRCT5H",
|
||||
"linux": "https://flathub.org/en/apps/app.feeddeck.feeddeck",
|
||||
};
|
||||
|
||||
const getPlatform = (): TPlatform | undefined => {
|
||||
|
||||
@@ -103,4 +103,12 @@ export const generalMetadata: Metadata = {
|
||||
url: "/og.png",
|
||||
},
|
||||
},
|
||||
itunes: {
|
||||
appId: "1494512160",
|
||||
},
|
||||
other: {
|
||||
"google-play-app": "app-id=io.feeddeck.feeddeck",
|
||||
"msApplication-ID": "26077RicoBerger.FeedDeck",
|
||||
"msApplication-PackageFamilyName": "26077RicoBerger.FeedDeck_2w82je6nmmv2c",
|
||||
},
|
||||
};
|
||||
|
||||