finished player UI with dynamic copy

This commit is contained in:
MSpeed 2020-09-08 21:54:47 +02:00
parent fa61f4e7a4
commit 6b1806d68b
23 changed files with 597 additions and 175 deletions

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Icon / ic_bulb</title>
<g id="Icon-/-ic_bulb" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M12,3 C11.54,3 11.07,3.04 10.6,3.14 C7.84,3.67 5.64,5.9 5.12,8.66 C4.64,11.27 5.6,13.67 7.34,15.22 C7.77,15.6 8,16.13 8,16.69 L8,19 C8,20.1 8.9,21 10,21 L10.28,21 C10.63,21.6 11.26,22 12,22 C12.74,22 13.38,21.6 13.72,21 L14,21 C15.1,21 16,20.1 16,19 L16,16.69 C16,16.14 16.22,15.6 16.64,15.23 C18.09,13.95 19,12.08 19,10 C19,6.13 15.87,3 12,3 Z M14,19 L10,19 L10,18 L14,18 L14,19 Z M14,17 L10,17 L10,16 L14,16 L14,17 Z M12.5,11.41 L12.5,14 L11.5,14 L11.5,11.41 L9.67,9.59 L10.38,8.88 L12,10.5 L13.62,8.88 L14.33,9.59 L12.5,11.41 Z" id="Shape" fill="#FFFFFF"></path>
<rect id="Path" x="0" y="0" width="24" height="24"></rect>
</g>
</svg>

After

Width:  |  Height:  |  Size: 974 B

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Icon / ic_corona</title>
<g id="Icon-/-ic_corona" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M21.25,10.5 C20.84,10.5 20.5,10.84 20.5,11.25 L18.96,11.25 C18.81,9.88 18.27,8.62 17.44,7.6 L18.53,6.51 L18.54,6.52 C18.83,6.81 19.31,6.81 19.6,6.52 C19.89,6.23 19.89,5.75 19.6,5.46 L18.54,4.4 C18.25,4.11 17.77,4.11 17.48,4.4 C17.19,4.69 17.19,5.16 17.47,5.45 L16.38,6.54 C15.36,5.72 14.11,5.18 12.74,5.03 L12.74,3.5 L12.75,3.5 C13.16,3.5 13.5,3.16 13.5,2.75 C13.5,2.34 13.16,2 12.75,2 L11.25,2 C10.84,2 10.5,2.34 10.5,2.75 C10.5,3.16 10.83,3.49 11.24,3.5 L11.24,5.05 C9.87,5.19 8.62,5.74 7.6,6.56 L6.51,5.47 L6.52,5.46 C6.81,5.17 6.81,4.69 6.52,4.4 C6.23,4.11 5.75,4.11 5.46,4.4 L4.4,5.46 C4.11,5.75 4.11,6.23 4.4,6.52 C4.69,6.81 5.16,6.81 5.45,6.53 L6.54,7.62 C5.72,8.64 5.18,9.88 5.04,11.25 L3.5,11.25 C3.5,10.84 3.16,10.5 2.75,10.5 C2.34,10.5 2,10.84 2,11.25 L2,12.75 C2,13.16 2.34,13.5 2.75,13.5 C3.16,13.5 3.5,13.16 3.5,12.75 L5.04,12.75 C5.19,14.12 5.73,15.36 6.54,16.38 L5.45,17.47 C5.16,17.18 4.69,17.19 4.4,17.48 C4.11,17.77 4.11,18.25 4.4,18.54 L5.46,19.6 C5.75,19.89 6.23,19.89 6.52,19.6 C6.81,19.31 6.81,18.83 6.52,18.54 L6.51,18.53 L7.6,17.44 C8.62,18.26 9.86,18.8 11.23,18.95 L11.23,20.5 C10.82,20.51 10.49,20.84 10.49,21.25 C10.49,21.66 10.83,22 11.24,22 L12.74,22 C13.15,22 13.49,21.66 13.49,21.25 C13.49,20.84 13.15,20.5 12.74,20.5 L12.73,20.5 L12.73,18.96 C14.1,18.82 15.35,18.27 16.37,17.45 L17.46,18.54 C17.17,18.83 17.18,19.3 17.47,19.59 C17.76,19.88 18.24,19.88 18.53,19.59 L19.59,18.53 C19.88,18.24 19.88,17.76 19.59,17.47 C19.3,17.18 18.82,17.18 18.53,17.47 L18.52,17.48 L17.43,16.39 C18.25,15.37 18.8,14.12 18.95,12.74 L20.49,12.74 C20.49,13.15 20.83,13.49 21.24,13.49 C21.65,13.49 21.99,13.15 21.99,12.74 L21.99,11.24 C22,10.84 21.66,10.5 21.25,10.5 Z M13.75,8 C14.3,8 14.75,8.45 14.75,9 C14.75,9.55 14.3,10 13.75,10 C13.2,10 12.75,9.55 12.75,9 C12.75,8.45 13.2,8 13.75,8 Z M12,13 C11.45,13 11,12.55 11,12 C11,11.45 11.45,11 12,11 C12.55,11 13,11.45 13,12 C13,12.55 12.55,13 12,13 Z M10.25,8 C10.8,8 11.25,8.45 11.25,9 C11.25,9.55 10.8,10 10.25,10 C9.7,10 9.25,9.55 9.25,9 C9.25,8.45 9.7,8 10.25,8 Z M8.5,13 C7.95,13 7.5,12.55 7.5,12 C7.5,11.45 7.95,11 8.5,11 C9.05,11 9.5,11.45 9.5,12 C9.5,12.55 9.05,13 8.5,13 Z M10.25,16 C9.7,16 9.25,15.55 9.25,15 C9.25,14.45 9.7,14 10.25,14 C10.8,14 11.25,14.45 11.25,15 C11.25,15.55 10.8,16 10.25,16 Z M13.75,16 C13.2,16 12.75,15.55 12.75,15 C12.75,14.45 13.2,14 13.75,14 C14.3,14 14.75,14.45 14.75,15 C14.75,15.55 14.3,16 13.75,16 Z M14.5,12 C14.5,11.45 14.95,11 15.5,11 C16.05,11 16.5,11.45 16.5,12 C16.5,12.55 16.05,13 15.5,13 C14.95,13 14.5,12.55 14.5,12 Z" id="Shape" fill="#FFFFFF"></path>
<rect id="Path" x="0" y="0" width="24" height="24"></rect>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Icon / ic_email</title>
<g id="Icon-/-ic_email" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M20,4 L4,4 C2.9,4 2.01,4.9 2.01,6 L2,18 C2,19.1 2.9,20 4,20 L20,20 C21.1,20 22,19.1 22,18 L22,6 C22,4.9 21.1,4 20,4 Z M20,8 L12,13 L4,8 L4,6 L12,11 L20,6 L20,8 Z" id="Shape" fill="#FFFFFF"></path>
<polygon id="Path" points="0 0 24 0 24 24 0 24"></polygon>
</g>
</svg>

After

Width:  |  Height:  |  Size: 607 B

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Icon / ic_gift</title>
<g id="Icon-/-ic_gift" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M9.32727273,2.0000386 C7.60909091,1.99058697 5.93636364,3.71786777 6.7,5.86273293 L3.81818182,5.86273293 C2.81402773,5.86273293 2,6.71254607 2,7.7608437 L2,9.65895446 C2,10.1831033 2.40701386,10.6080098 2.90909091,10.6080098 L11.0909091,10.6080098 L11.0909091,7.7608437 L12.9090909,7.7608437 L12.9090909,10.6080098 L21.0909091,10.6080098 C21.5929861,10.6080098 22,10.1831033 22,9.65895446 L22,7.7608437 C22,6.71254607 21.1859723,5.86273293 20.1818182,5.86273293 L17.3,5.86273293 C18.3636364,2.75932183 14.3636364,0.5670039 12.5181818,3.24334008 L12,3.96462217 L11.4818182,3.22435897 C10.9090909,2.37969968 10.1181818,2.00956808 9.32727273,2.0000386 M9.27272727,3.96462217 C10.0818182,3.96462217 10.4909091,4.98960198 9.91818182,5.58750687 C9.34545455,6.18541176 8.36363636,5.75833684 8.36363636,4.91367755 C8.36363636,4.38952874 8.77065023,3.96462217 9.27272727,3.96462217 M14.7272727,3.96462217 C15.5363636,3.96462217 15.9454545,4.98960198 15.3727273,5.58750687 C14.8,6.18541176 13.8181818,5.75833684 13.8181818,4.91367755 C13.8181818,4.38952874 14.2251957,3.96462217 14.7272727,3.96462217 M2.90909091,11.5570652 L2.90909091,19.1495083 C2.90909091,20.1978059 3.72311864,21.047619 4.72727273,21.047619 L19.2727273,21.047619 C20.2768814,21.047619 21.0909091,20.1978059 21.0909091,19.1495083 L21.0909091,11.5570652 L12.9090909,11.5570652 L12.9090909,19.1495083 L11.0909091,19.1495083 L11.0909091,11.5570652 L2.90909091,11.5570652 Z" id="Shape" fill="#FFFFFF"></path>
<polygon id="Path" points="0 0 24 0 24 24 0 24"></polygon>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Icon / ic_happyface</title>
<g id="Icon-/-ic_happyface" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M11.99,2 C17.52,2 22,6.48 22,12 C22,17.52 17.52,22 11.99,22 C6.47,22 2,17.52 2,12 C2,6.48 6.47,2 11.99,2 Z M12,4 C7.58,4 4,7.58 4,12 C4,16.42 7.58,20 12,20 C16.42,20 20,16.42 20,12 C20,7.58 16.42,4 12,4 Z M17,14 C16.22,16.34 14.28,18 12,18 C9.72,18 7.78,16.34 7,14 L7,14 Z M15.5,8 C16.3284271,8 17,8.67157288 17,9.5 C17,10.3284271 16.3284271,11 15.5,11 C14.6715729,11 14,10.3284271 14,9.5 C14,8.67157288 14.6715729,8 15.5,8 Z M8.5,8 C9.32842712,8 10,8.67157288 10,9.5 C10,10.3284271 9.32842712,11 8.5,11 C7.67157288,11 7,10.3284271 7,9.5 C7,8.67157288 7.67157288,8 8.5,8 Z" id="Shape" fill="#FFFFFF"></path>
<polygon id="Path" points="0 0 24 0 24 24 0 24"></polygon>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Icon / ic_help</title>
<g id="Icon-/-ic_help" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M12,2 C6.48,2 2,6.48 2,12 C2,17.52 6.48,22 12,22 C17.52,22 22,17.52 22,12 C22,6.48 17.52,2 12,2 Z M13,19 L11,19 L11,17 L13,17 L13,19 Z M15.07,11.25 L14.17,12.17 C13.45,12.9 13,13.5 13,15 L11,15 L11,14.5 C11,13.4 11.45,12.4 12.17,11.67 L13.41,10.41 C13.78,10.05 14,9.55 14,9 C14,7.9 13.1,7 12,7 C10.9,7 10,7.9 10,9 L8,9 C8,6.79 9.79,5 12,5 C14.21,5 16,6.79 16,9 C16,9.88 15.64,10.68 15.07,11.25 Z" id="Shape" fill="#FFFFFF"></path>
<polygon id="Path" points="0 0 24 0 24 24 0 24"></polygon>
</g>
</svg>

After

Width:  |  Height:  |  Size: 839 B

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Icon / ic_instagram</title>
<g id="Icon-/-ic_instagram" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M7.8,2 L16.2,2 C19.4,2 22,4.6 22,7.8 L22,16.2 C22,19.4032515 19.4032515,22 16.2,22 L7.8,22 C4.6,22 2,19.4 2,16.2 L2,7.8 C2,4.59674845 4.59674845,2 7.8,2 M7.6,4 C5.6117749,4 4,5.6117749 4,7.6 L4,16.4 C4,18.39 5.61,20 7.6,20 L16.4,20 C18.3882251,20 20,18.3882251 20,16.4 L20,7.6 C20,5.61 18.39,4 16.4,4 L7.6,4 M17.25,5.5 C17.9403559,5.5 18.5,6.05964406 18.5,6.75 C18.5,7.44035594 17.9403559,8 17.25,8 C16.5596441,8 16,7.44035594 16,6.75 C16,6.05964406 16.5596441,5.5 17.25,5.5 M12,7 C14.7614237,7 17,9.23857625 17,12 C17,14.7614237 14.7614237,17 12,17 C9.23857625,17 7,14.7614237 7,12 C7,9.23857625 9.23857625,7 12,7 M12,9 C10.3431458,9 9,10.3431458 9,12 C9,13.6568542 10.3431458,15 12,15 C13.6568542,15 15,13.6568542 15,12 C15,10.3431458 13.6568542,9 12,9 Z" id="Shape" fill="#FFFFFF"></path>
<polygon id="Path" points="0 0 24 0 24 24 0 24"></polygon>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Icon / ic_people</title>
<g id="Icon-/-ic_people" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M6,2 C6,4.75 8.24,6.99 10.99,7 L10.99,7 L13.53,7 C14.83,7 15.5,7.72 15.89,8.11 L15.89,8.11 L20.36,12.59 L18.95,14 L15,10.05 L15,22 L13,22 L13,16 L11,16 L11,22 L9,22 L9,8.71 C6.11,7.84 4,5.16 4,2 L4,2 Z M12,2 C13.1045695,2 14,2.8954305 14,4 C14,5.1045695 13.1045695,6 12,6 C10.8954305,6 10,5.1045695 10,4 C10,2.8954305 10.8954305,2 12,2 Z" id="Shape" fill="#FFFFFF"></path>
<rect id="Path" x="0" y="0" width="24" height="24"></rect>
</g>
</svg>

After

Width:  |  Height:  |  Size: 785 B

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Icon / ic_psychology</title>
<g id="Icon-/-ic_psychology" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M13,3 C16.87,3 20,6.13 20,10 C20,12.79 18.36,15.2 16,16.32 L16,16.32 L16,21 L9,21 L9,18 L8,18 C6.9,18 6,17.1 6,16 L6,16 L6,13 L4.5,13 C4.09,13 3.85,12.53 4.1,12.2 L4.1,12.2 L6.02,9.64 C6.2,5.94 9.25,3 13,3 Z M13.8,6 L12.2,6 C12.1,6 12.02,6.07 12,6.17 L12,6.17 L11.85,7.23 C11.61,7.33 11.38,7.47 11.18,7.62 L11.18,7.62 L10.18,7.22 C10.09,7.19 9.99,7.22 9.94,7.31 L9.94,7.31 L9.14,8.69 C9.09,8.79 9.11,8.89 9.19,8.95 L9.19,8.95 L10.04,9.61 C10.02,9.73 10,9.87 10,10 C10,10.13 10.01,10.26 10.02,10.39 L10.02,10.39 L9.18,11.05 C9.1,11.11 9.08,11.22 9.13,11.3 L9.13,11.3 L9.93,12.69 C9.98,12.78 10.09,12.81 10.18,12.78 L10.18,12.78 L11.17,12.38 C11.38,12.54 11.6,12.67 11.85,12.77 L11.85,12.77 L12,13.83 C12.02,13.93 12.1,14 12.2,14 L12.2,14 L13.8,14 C13.9,14 13.99,13.93 14,13.83 L14,13.83 L14.16,12.77 C14.4,12.67 14.62,12.54 14.83,12.38 L14.83,12.38 L15.82,12.78 C15.9,12.81 16.01,12.78 16.06,12.69 L16.06,12.69 L16.86,11.3 C16.91,11.21 16.89,11.11 16.81,11.05 L16.81,11.05 L15.98,10.39 C15.99,10.26 16,10.13 16,10 C16,9.86 15.99,9.73 15.96,9.61 L15.96,9.61 L16.81,8.95 C16.89,8.89 16.91,8.78 16.86,8.69 L16.86,8.69 L16.06,7.31 C16.02,7.22 15.91,7.19 15.82,7.22 L15.82,7.22 L14.82,7.62 C14.61,7.46 14.39,7.33 14.15,7.23 L14.15,7.23 L14,6.17 C13.98,6.07 13.9,6 13.8,6 L13.8,6 Z M13,8.57 C13.79,8.57 14.43,9.21 14.43,10 C14.43,10.79 13.79,11.43 13,11.43 C12.21,11.43 11.57,10.79 11.57,10 C11.57,9.21 12.21,8.57 13,8.57 Z" id="Shape" fill="#FFFFFF"></path>
<rect id="Path" x="0" y="0" width="24" height="24"></rect>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Icon / ic_review</title>
<g id="Icon-/-ic_review" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M20,2 L4,2 C2.9,2 2.01,2.9 2.01,4 L2,22 L6,18 L20,18 C21.1,18 22,17.1 22,16 L22,4 C22,2.9 21.1,2 20,2 Z M6,14 L6,11.53 L12.88,4.65 C13.08,4.45 13.39,4.45 13.59,4.65 L15.36,6.42 C15.56,6.62 15.56,6.93 15.36,7.13 L8.47,14 L6,14 Z M18,14 L10.5,14 L12.5,12 L18,12 L18,14 Z" id="Shape" fill="#FFFFFF"></path>
<polygon id="Path" points="0 0 24 0 24 24 0 24"></polygon>
</g>
</svg>

After

Width:  |  Height:  |  Size: 716 B

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Icon / ic_support</title>
<g id="Icon-/-ic_support" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M12,2 C6.48,2 2,6.48 2,12 C2,17.52 6.48,22 12,22 C17.52,22 22,17.52 22,12 C22,6.48 17.52,2 12,2 Z M19.46,9.12 L16.68,10.27 C16.17,8.91 15.1,7.83 13.73,7.33 L14.88,4.55 C16.98,5.35 18.65,7.02 19.46,9.12 Z M12,15 C10.34,15 9,13.66 9,12 C9,10.34 10.34,9 12,9 C13.66,9 15,10.34 15,12 C15,13.66 13.66,15 12,15 Z M9.13,4.54 L10.3,7.32 C8.92,7.82 7.83,8.91 7.32,10.29 L4.54,9.13 C5.35,7.02 7.02,5.35 9.13,4.54 Z M4.54,14.87 L7.32,13.72 C7.83,15.1 8.91,16.18 10.29,16.68 L9.12,19.46 C7.02,18.65 5.35,16.98 4.54,14.87 Z M14.88,19.46 L13.73,16.68 C15.1,16.17 16.18,15.09 16.68,13.71 L19.46,14.88 C18.65,16.98 16.98,18.65 14.88,19.46 Z" id="Shape" fill="#FFFFFF"></path>
<rect id="Path" x="0" y="0" width="24" height="24"></rect>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Icon / ic_twitter</title>
<g id="Icon-/-ic_twitter" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M22.92,6 C22.15,6.35 21.32,6.58 20.46,6.69 C21.34,6.16 22.02,5.32 22.34,4.31 C21.51,4.81 20.59,5.16 19.62,5.36 C18.83,4.5 17.72,4 16.46,4 C14.11,4 12.19,5.92 12.19,8.29 C12.19,8.63 12.23,8.96 12.3,9.27 C8.74,9.09 5.57,7.38 3.46,4.79 C3.09,5.42 2.88,6.16 2.88,6.94 C2.88,8.43 3.63,9.75 4.79,10.5 C4.08,10.5 3.42,10.3 2.84,10 C2.84,10 2.84,10 2.84,10.03 C2.84,12.11 4.32,13.85 6.28,14.24 C5.92,14.34 5.54,14.39 5.15,14.39 C4.88,14.39 4.61,14.36 4.35,14.31 C4.89,16 6.46,17.26 8.35,17.29 C6.89,18.45 5.04,19.13 3.02,19.13 C2.68,19.13 2.34,19.11 2,19.07 C3.9,20.29 6.16,21 8.58,21 C16.46,21 20.79,14.46 20.79,8.79 C20.79,8.6 20.79,8.42 20.78,8.23 C21.62,7.63 22.34,6.87 22.92,6 Z" id="Shape" fill="#FFFFFF"></path>
<polygon id="Path" points="0 0 24 0 24 24 0 24"></polygon>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -2,7 +2,7 @@
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/Users/mike/flutter"
export "FLUTTER_APPLICATION_PATH=/Users/mike/AndroidStudioProjects/meditoapp"
export "FLUTTER_TARGET=/Users/mike/AndroidStudioProjects/meditoapp/lib/main.dart"
export "FLUTTER_TARGET=lib/main.dart"
export "FLUTTER_BUILD_DIR=build"
export "SYMROOT=${SOURCE_ROOT}/../build/ios"
export "OTHER_LDFLAGS=$(inherited) -framework Flutter"
@ -10,6 +10,6 @@ export "FLUTTER_FRAMEWORK_DIR=/Users/mike/flutter/bin/cache/artifacts/engine/ios
export "FLUTTER_BUILD_NAME=1.0.39"
export "FLUTTER_BUILD_NUMBER=369"
export "DART_OBFUSCATION=false"
export "TRACK_WIDGET_CREATION=true"
export "TRACK_WIDGET_CREATION=false"
export "TREE_SHAKE_ICONS=false"
export "PACKAGE_CONFIG=.packages"

View File

@ -71,7 +71,7 @@ Container getAttrWidget(BuildContext context, licenseTitle, sourceUrl,
Future<dynamic> checkFileExists(Files currentFile) async {
String dir = (await getApplicationSupportDirectory()).path;
var name = currentFile.filename;
var name = currentFile.filename.replaceAll(" ", "%20");
File file = new File('$dir/$name');
var exists = await file.exists();
print('$exists $file');
@ -87,27 +87,6 @@ Future getAttributions(String attrId) async {
return attrs.data.content;
}
Future<dynamic> downloadFile(Files currentFile) async {
getAttributions(currentFile.attributions);
String dir = (await getApplicationSupportDirectory()).path;
var name = currentFile.filename;
File file = new File('$dir/$name');
if (await file.exists()) return null;
var request = await http.get(currentFile.url);
if (request.statusCode < 200 || request.statusCode > 300) {
throw HttpException("http exception erro getting file");
}
var bytes = request.bodyBytes;
await file.writeAsBytes(bytes);
saveFileToDownloadedFilesList(currentFile);
print(file.path);
}
Future<dynamic> downloadBGMusicFromURL(String url, String name) async {
String dir = (await getApplicationSupportDirectory()).path;
name = name.replaceAll(" ", "%20");
@ -147,6 +126,28 @@ Future<dynamic> removeFile(Files currentFile) async {
}
}
Future<dynamic> downloadFile(Files currentFile) async {
getAttributions(currentFile.attributions);
String dir = (await getApplicationSupportDirectory()).path;
var name = currentFile.filename.replaceAll(" ", "%20");
File file = new File('$dir/$name');
if (await file.exists()) return null;
var request = await http.get(currentFile.url);
if (request.statusCode < 200 || request.statusCode > 300) {
throw HttpException("http exception erro getting file");
}
var bytes = request.bodyBytes;
await file.writeAsBytes(bytes);
saveFileToDownloadedFilesList(currentFile);
print(file.path);
}
Future<dynamic> getDownload(String filename) async {
var path = (await getApplicationSupportDirectory()).path;
filename = filename.replaceAll(" ", "%20");
@ -155,37 +156,4 @@ Future<dynamic> getDownload(String filename) async {
return file.absolute.path;
else
return null;
}
/// Generates a 200x200 png, with randomized colors, to use as art for the
/// notification/lockscreen.
Future<Uint8List> generateImageBytes() async {
// Random color generation methods: pick contrasting hues.
final HSLColor bgHslColor = HSLColor.fromColor(MeditoColors.darkBGColor);
final HSLColor fgHslColor = HSLColor.fromColor(MeditoColors.lightColor);
final Size size = const Size(200.0, 200.0);
final Offset center = const Offset(100.0, 100.0);
final ui.PictureRecorder recorder = ui.PictureRecorder();
final Rect rect = Offset.zero & size;
final Canvas canvas = Canvas(recorder, rect);
final Paint bgPaint = Paint()
..style = PaintingStyle.fill
..color = bgHslColor.toColor();
final Paint fgPaint = Paint()
..style = PaintingStyle.stroke
..color = bgHslColor.toColor()
..strokeWidth = 8;
// Draw background color.
canvas.drawRect(rect, bgPaint);
// Draw 5 inset squares around the center.
canvas.drawRect(
Rect.fromCenter(center: center, width: 40.0, height: 40.0), fgPaint);
// Render to image, then compress to PNG ByteData, then return as Uint8List.
final ui.Image image = await recorder
.endRecording()
.toImage(size.width.toInt(), size.height.toInt());
final ByteData encodedImageData =
await image.toByteData(format: ui.ImageByteFormat.png);
return encodedImageData.buffer.asUint8List();
}
}

View File

@ -7,10 +7,13 @@ import 'package:Medito/tracking/tracking.dart';
import 'package:Medito/utils/colors.dart';
import 'package:Medito/utils/stats_utils.dart';
import 'package:Medito/utils/utils.dart';
import 'package:Medito/viewmodel/audio_complete_copy_provider.dart';
import 'package:audio_service/audio_service.dart';
import 'package:audio_session/audio_session.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:just_audio/just_audio.dart';
import 'package:rxdart/rxdart.dart';
import 'package:share/share.dart';
@ -21,9 +24,13 @@ class PlayerWidget extends StatefulWidget {
}
class _PlayerWidgetState extends State<PlayerWidget> {
final String completedText = "Well done for taking time for yourself!";
final String completedMoreText =
String completedText = "Well done for taking time for yourself!";
String completedMoreText =
"Taking care of yourself is important. Were here to help you do it, for free, forever.";
String buttonLabel = "Donate";
String buttonUrl = "http://meditofoundation.org/donate";
String buttonIcon = "assets/images/ic_gift.svg";
String artUrl;
Color textColor;
Color coverColorAsColor;
@ -33,82 +40,129 @@ class _PlayerWidgetState extends State<PlayerWidget> {
AudioService.stop();
super.dispose();
}
@override
void initState() {
super.initState();
AudioCompleteCopyProvider provider = AudioCompleteCopyProvider();
provider.fetchCopy().then((value) {
completedText = value.title;
completedMoreText = value.subtitle;
buttonLabel = value.buttonLabel;
buttonUrl = value.buttonDestination;
buttonIcon.replaceFirst("ic_gift", value.buttonIcon);
return null;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
Center(
child: StreamBuilder<ScreenState>(
stream: _screenStateStream,
builder: (context, snapshot) {
final screenState = snapshot.data;
final mediaItem = screenState?.mediaItem;
final state = screenState?.playbackState;
final processingState =
state?.processingState ?? AudioProcessingState.none;
final playing = state?.playing ?? false;
backgroundColor: MeditoColors.midnight,
body: StreamBuilder<ScreenState>(
stream: _screenStateStream,
builder: (context, snapshot) {
final screenState = snapshot.data;
final mediaItem = screenState?.mediaItem;
final state = screenState?.playbackState;
final processingState =
state?.processingState ?? AudioProcessingState.none;
final playing = state?.playing ?? false;
getTextColor(mediaItem);
getCoverColor(mediaItem);
getArtUrl(mediaItem);
getTextColor(mediaItem);
getCoverColor(mediaItem);
getArtUrl(mediaItem);
return Column(
children: <Widget>[
Expanded(
child: Container(
color: coverColorAsColor,
child: Center(
child: FractionallySizedBox(
widthFactor: .43,
child: Image.network(
artUrl ?? 'https://i.imgur.com/QUmnKlp.png',
)),
return Stack(
children: [
Column(
children: <Widget>[
Expanded(
child: Container(
color: coverColorAsColor,
child: Center(
child: FractionallySizedBox(
widthFactor: .43,
child: artUrl != null
? Image.network(artUrl)
: Container()),
),
),
),
Padding(
padding: const EdgeInsets.only(
top: 28.0, left: 16.0, bottom: 8.0, right: 16.0),
child: Row(
children: [
Expanded(
child: Text(
mediaItem?.title ?? completedText,
style: GoogleFonts.merriweather().copyWith(
letterSpacing: 0.4,
fontSize: 26.0,
fontWeight: FontWeight.w700),
),
),
),
],
),
Padding(
padding: const EdgeInsets.only(
top: 28.0, left: 16.0, bottom: 8.0, right: 16.0),
child: Row(children: [
Expanded(
child: Text(
mediaItem?.title ?? completedText,
),
)
])),
Padding(
padding: const EdgeInsets.only(
left: 16.0, bottom: 20.0, right: 16.0),
child: Row(children: [
mediaItem?.extras != null
? Text(mediaItem?.extras['attr'] ?? 'Loading...')
: Expanded(child: Text(completedMoreText)),
]),
),
Padding(
padding: const EdgeInsets.only(
left: 16.0, bottom: 20.0, right: 16.0),
child: Row(children: [
mediaItem?.extras != null
? Text(
mediaItem?.extras['attr'] ?? 'Loading...',
style: Theme.of(context)
.textTheme
.headline1
.copyWith(color: MeditoColors.newGrey),
)
: Expanded(
child: Text(
completedMoreText,
style: Theme.of(context)
.textTheme
.headline1
.copyWith(color: MeditoColors.newGrey),
)),
]),
),
mediaItem == null
? Container()
: positionIndicator(mediaItem, state, coverColorAsColor),
Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
children: [
(processingState == AudioProcessingState.buffering ||
processingState ==
AudioProcessingState.connecting)
? buildIndicatorRow()
: Expanded(
child: mediaItem == null
? getDonateAndShareButton()
: getPlayingOrPausedButton(playing),
),
],
),
mediaItem == null
? Container()
: positionIndicator(
mediaItem, state, coverColorAsColor),
Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
children: [
(processingState == AudioProcessingState.buffering ||
processingState ==
AudioProcessingState.connecting)
? buildIndicatorRow()
: Expanded(
child: mediaItem == null
? getDonateAndShareButton()
: getPlayingOrPausedButton(playing),
),
],
),
),
],
);
),
],
),
SafeArea(
child: Padding(
padding: EdgeInsets.only(left: 12.0),
child: IconButton(
icon: Icon(Icons.close),
onPressed: _onBackPressed,
color: textColor,
),
),
),
],
);
// return Column(
// mainAxisAlignment: MainAxisAlignment.center,
@ -150,20 +204,7 @@ class _PlayerWidgetState extends State<PlayerWidget> {
// ],
// ],
// );
},
),
),
SafeArea(
child: Padding(
padding: EdgeInsets.only(left: 12.0),
child: IconButton(
icon: Icon(Icons.close),
onPressed: _onBackPressed,
color: textColor,
),
),
),
],
},
),
);
}
@ -253,16 +294,16 @@ class _PlayerWidgetState extends State<PlayerWidget> {
Navigator.popUntil(context, ModalRoute.withName("/nav"));
}
String donateUrl = "https://meditofoundation.org/donate/";
Widget getDonateAndShareButton() {
return Column(
children: <Widget>[
PlayerButton(
icon: Icons.card_giftcard,
image: SvgPicture.asset(buttonIcon,
color: textColor,
),
onPressed: _launchDonate,
bgColor: coverColorAsColor,
text: "Donate",
text: buttonLabel,
textColor: textColor),
Container(height: 8),
PlayerButton(
@ -277,11 +318,12 @@ class _PlayerWidgetState extends State<PlayerWidget> {
}
Future<void> _launchDonate() {
return launchUrl(donateUrl);
return launchUrl(buttonUrl);
}
Future<void> _share() {
Share.share('Just meditated with Medio!!');
return null;
}
}
@ -291,6 +333,7 @@ class PlayerButton extends StatelessWidget {
final Color bgColor;
final String text;
final Color textColor;
final SvgPicture image;
PlayerButton(
{Key key,
@ -298,7 +341,8 @@ class PlayerButton extends StatelessWidget {
this.onPressed,
this.bgColor,
this.text,
this.textColor})
this.textColor,
this.image})
: super(key: key);
@override
@ -312,11 +356,15 @@ class PlayerButton extends StatelessWidget {
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
icon,
size: 24,
color: textColor,
),
image != null
? image
: Icon(
icon,
size: 24,
color: text == null
? MeditoColors.lightTextColor
: textColor,
),
text == null
? Container()
: Padding(
@ -472,29 +520,19 @@ class AudioPlayerTask extends BackgroundAudioTask {
this.mediaItem = value;
});
var source;
// Load and broadcast the queue
AudioServiceBackground.setQueue([mediaItem]);
try {
await getDownload(mediaItem.extras['location']).then((data) {
await getDownload(mediaItem.extras['location']).then((data) async {
if (data == null) {
source = ConcatenatingAudioSource(
children: [mediaItem]
.map((item) => AudioSource.uri(Uri.parse(item.id)))
.toList(),
);
_duration = await _player.setUrl(mediaItem.id);
} else {
source = ConcatenatingAudioSource(
children: [AudioSource.uri(Uri.parse(data))],
);
_duration = await _player.setFilePath(data);
}
playBgMusic(mediaItem.extras['bgMusic']);
onPlay();
});
_duration = await _player.load(source);
playBgMusic(mediaItem.extras['bgMusic']);
onPlay();
} catch (e) {
print("Error: $e");
onStop();
@ -642,8 +680,8 @@ class AudioPlayerTask extends BackgroundAudioTask {
}
}
void playBgMusic(bgMusic) {
if (bgMusic != null) {
void playBgMusic(String bgMusic) {
if (bgMusic != null && bgMusic.isNotEmpty && bgMusic != "null") {
_bgPlayer.setFilePath(bgMusic);
_bgPlayer.setVolume(initialBgVolume);
_bgPlayer.setLoopMode(LoopMode.one);
@ -711,14 +749,15 @@ class Seeker {
}
}
Future<bool> start() {
Future<bool> start(String coverColor) {
int color = getColorFromHex(coverColor);
AudioService.connect();
return AudioService.start(
backgroundTaskEntrypoint: _audioPlayerTaskEntrypoint,
androidNotificationChannelName: 'Audio Service Demo',
// Enable this if you want the Android service to exit the foreground state on pause.
//androidStopForegroundOnPause: true,
androidNotificationColor: 0xFF2196f3,
androidNotificationColor: color,
androidNotificationIcon: 'drawable/logo',
androidEnableQueue: true,
);

View File

@ -0,0 +1,273 @@
class AudioCompleteCopyResponse {
int code;
Data data;
String status;
String type;
AudioCompleteCopyResponse({this.code, this.data, this.status, this.type});
AudioCompleteCopyResponse.fromJson(Map<String, dynamic> json) {
code = json['code'];
data = json['data'] != null ? new Data.fromJson(json['data']) : null;
status = json['status'];
type = json['type'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['code'] = this.code;
if (this.data != null) {
data['data'] = this.data.toJson();
}
data['status'] = this.status;
data['type'] = this.type;
return data;
}
}
class Data {
Content content;
String id;
Null num;
Options options;
Parent parent;
String slug;
String status;
String template;
String title;
String url;
Data(
{this.content,
this.id,
this.num,
this.options,
this.parent,
this.slug,
this.status,
this.template,
this.title,
this.url});
Data.fromJson(Map<String, dynamic> json) {
content =
json['content'] != null ? new Content.fromJson(json['content']) : null;
id = json['id'];
num = json['num'];
options =
json['options'] != null ? new Options.fromJson(json['options']) : null;
parent =
json['parent'] != null ? new Parent.fromJson(json['parent']) : null;
slug = json['slug'];
status = json['status'];
template = json['template'];
title = json['title'];
url = json['url'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.content != null) {
data['content'] = this.content.toJson();
}
data['id'] = this.id;
data['num'] = this.num;
if (this.options != null) {
data['options'] = this.options.toJson();
}
if (this.parent != null) {
data['parent'] = this.parent.toJson();
}
data['slug'] = this.slug;
data['status'] = this.status;
data['template'] = this.template;
data['title'] = this.title;
data['url'] = this.url;
return data;
}
}
class Content {
List<Versions> versions;
String title;
Content({this.versions, this.title});
Content.fromJson(Map<String, dynamic> json) {
if (json['versions'] != null) {
versions = new List<Versions>();
json['versions'].forEach((v) {
versions.add(new Versions.fromJson(v));
});
}
title = json['title'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.versions != null) {
data['versions'] = this.versions.map((v) => v.toJson()).toList();
}
data['title'] = this.title;
return data;
}
}
class Versions {
bool sticky;
String title;
String subtitle;
String buttonIcon;
String buttonLabel;
String buttonDestination;
Versions(
{this.sticky,
this.title,
this.subtitle,
this.buttonIcon,
this.buttonLabel,
this.buttonDestination});
Versions.fromJson(Map<String, dynamic> json) {
sticky = json['sticky'];
title = json['title'];
subtitle = json['subtitle'];
buttonIcon = json['button_icon'];
buttonLabel = json['button_label'];
buttonDestination = json['button_destination'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['sticky'] = this.sticky;
data['title'] = this.title;
data['subtitle'] = this.subtitle;
data['button_icon'] = this.buttonIcon;
data['button_label'] = this.buttonLabel;
data['button_destination'] = this.buttonDestination;
return data;
}
}
class Options {
bool changeSlug;
bool changeStatus;
bool changeTemplate;
bool changeTitle;
bool create;
bool delete;
bool duplicate;
bool read;
bool preview;
bool sort;
bool update;
Options(
{this.changeSlug,
this.changeStatus,
this.changeTemplate,
this.changeTitle,
this.create,
this.delete,
this.duplicate,
this.read,
this.preview,
this.sort,
this.update});
Options.fromJson(Map<String, dynamic> json) {
changeSlug = json['changeSlug'];
changeStatus = json['changeStatus'];
changeTemplate = json['changeTemplate'];
changeTitle = json['changeTitle'];
create = json['create'];
delete = json['delete'];
duplicate = json['duplicate'];
read = json['read'];
preview = json['preview'];
sort = json['sort'];
update = json['update'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['changeSlug'] = this.changeSlug;
data['changeStatus'] = this.changeStatus;
data['changeTemplate'] = this.changeTemplate;
data['changeTitle'] = this.changeTitle;
data['create'] = this.create;
data['delete'] = this.delete;
data['duplicate'] = this.duplicate;
data['read'] = this.read;
data['preview'] = this.preview;
data['sort'] = this.sort;
data['update'] = this.update;
return data;
}
}
class Parent {
Null buttonLabel;
Null contentPath;
Null contentText;
Null description;
String id;
Null illustrationUrl;
Null num;
Null pathTemplate;
Null primaryColor;
Null secondaryColor;
String template;
String title;
String url;
Parent(
{this.buttonLabel,
this.contentPath,
this.contentText,
this.description,
this.id,
this.illustrationUrl,
this.num,
this.pathTemplate,
this.primaryColor,
this.secondaryColor,
this.template,
this.title,
this.url});
Parent.fromJson(Map<String, dynamic> json) {
buttonLabel = json['buttonLabel'];
contentPath = json['contentPath'];
contentText = json['contentText'];
description = json['description'];
id = json['id'];
illustrationUrl = json['illustrationUrl'];
num = json['num'];
pathTemplate = json['pathTemplate'];
primaryColor = json['primaryColor'];
secondaryColor = json['secondaryColor'];
template = json['template'];
title = json['title'];
url = json['url'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['buttonLabel'] = this.buttonLabel;
data['contentPath'] = this.contentPath;
data['contentText'] = this.contentText;
data['description'] = this.description;
data['id'] = this.id;
data['illustrationUrl'] = this.illustrationUrl;
data['num'] = this.num;
data['pathTemplate'] = this.pathTemplate;
data['primaryColor'] = this.primaryColor;
data['secondaryColor'] = this.secondaryColor;
data['template'] = this.template;
data['title'] = this.title;
data['url'] = this.url;
return data;
}
}

View File

@ -25,4 +25,7 @@ class MeditoColors {
static var darkBGColor = Color(0xff22282D);
static var lightBlack = Color(0xb2000000);
static var almostBlack = Color(0xEE000000);
static const newGrey = Color(0xffb6b6b8);
static const midnight = Color(0xff111213);
}

View File

@ -123,6 +123,14 @@ Future<bool> checkConnectivity() async {
return false;
}
int getColorFromHex(String hexColor) {
hexColor = hexColor.toUpperCase().replaceAll("#", "");
if (hexColor.length == 6) {
hexColor = "FF" + hexColor;
}
return int.parse(hexColor, radix: 16);
}
Color parseColor(String color) {
if (color == null || color.length == 0) return Colors.white;

View File

@ -0,0 +1,33 @@
import 'dart:async';
import 'package:Medito/data/audio_complete_copy_response.dart';
import 'package:Medito/viewmodel/http_get.dart';
import 'package:flutter/foundation.dart';
class AudioCompleteCopyProvider extends ChangeNotifier {
var baseUrl = 'https://medito.app/api/pages';
Future<Versions> fetchCopy() async {
try {
final response = await httpGet(baseUrl + "/service+audiocompletecopy");
if (response != null) {
var copy = AudioCompleteCopyResponse.fromJson(response);
var versions = copy.data.content.versions;
var sticky = versions.firstWhere((element) => element?.sticky,
orElse: () => null);
if (sticky != null) {
return sticky;
} else {
versions.shuffle();
return versions.first;
}
}
return null;
} on Exception {
return null;
}
}
}

View File

@ -41,7 +41,7 @@ Future httpGet(String url, {bool skipCache = false}) async {
headers: {HttpHeaders.authorizationHeader: basicAuth},
);
if (response.statusCode != 200) {
if (response.statusCode == 200) {
await writeJSONToCache(response.body, url);
}
return json.decode(response.body);

View File

@ -280,7 +280,7 @@ class _FolderNavWidgetState extends State<FolderNavWidget>
_viewModel.currentlySelectedFile,
attributionsContent))
.then((value) {
start().then((value) {
start(coverColor).then((value) {
Navigator.push(context, MaterialPageRoute(builder: (c) {
return PlayerWidget();
}));

View File

@ -467,7 +467,7 @@ class TileListState extends State<TileList> {
await MediaLibrary.saveMediaLibrary(description, title, fileTapped,
coverArt, textColor, coverColor, bgMusic, listItem, att);
}).then((value) {
start().then((value) => Navigator.push(
start(coverColor).then((value) => Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return PlayerWidget();

View File

@ -33,6 +33,7 @@ dependencies:
share: ^0.6.5
firebase_core: ^0.5.0
firebase_analytics: ^6.0.0
provider: ^4.3.2+2
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
@ -52,6 +53,7 @@ flutter:
- assets/images/ic_document.svg
- assets/images/ic_folder.svg
- assets/images/icon_ic_logo.svg
- assets/images/ic_gift.svg
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in