Compare commits
14 Commits
fec590b16e
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 5e83740f57 | |||
| eba444459b | |||
| 745d843af7 | |||
| 6827a2994a | |||
| a3e3544ee8 | |||
| ae1b9ca6e8 | |||
| b1904a0a7d | |||
| 123d4436d5 | |||
| 35ebf90f0a | |||
| 01f6509c99 | |||
| f4273ebfd6 | |||
| f46db58ed1 | |||
| 901a69bb91 | |||
| 5212d7bf70 |
3
.gitignore
vendored
@@ -1,3 +1,6 @@
|
||||
imagini.db
|
||||
media/
|
||||
notes
|
||||
web/node_modules/
|
||||
web/dist/
|
||||
build/
|
||||
|
||||
56
README.md
@@ -1,22 +1,44 @@
|
||||
#uImagini
|
||||
<p align="center">
|
||||
<img src="https://gitea.va.reichard.io/evan/imagini/raw/branch/master/assets/imagini_full.png" width="300">
|
||||
</p>
|
||||
|
||||
## Running Server
|
||||
# cd ./cmd/
|
||||
CONFIG_PATH=$(pwd) DATA_PATH=$(pwd) go run main.go serve
|
||||
---
|
||||
|
||||
## Generate GraphQL Models
|
||||
# cd ./cmd/
|
||||
A self hosted photo library with user management & authentication. Cross platform Client supporting Android, iOS, and Web.
|
||||
|
||||
## Client
|
||||
See `web_native` [subfolder](./web_native/README.md)
|
||||
|
||||
## Server
|
||||
### Features / Roadmap
|
||||
- [DONE] DB w/ user management - bcrypt salt & hash
|
||||
- [DONE] JWT Access & Refresh Tokens
|
||||
- [DONE] GraphQL API
|
||||
- [DONE] GraphQL multipart upload
|
||||
- [DONE] GraphQL basic filtering, ordering, pagination
|
||||
- [DONE] Uploading images - exif extraction (load db with lat, long, etc)
|
||||
- [DONE] Dynamic image conversion (heif support, width params)
|
||||
|
||||
- [TODO] ALL the tests
|
||||
- [TODO] GraphQL & DB deletes & update
|
||||
- [TODO] Dockerfile
|
||||
- [TODO] Resolving GraphQL nested queries (e.g. albums, tags)
|
||||
- [TODO] GraphQL nested filters
|
||||
- [TODO] Lots more... TBD
|
||||
|
||||
### Dependencies
|
||||
|
||||
- libvips 8.8+
|
||||
|
||||
### Running
|
||||
|
||||
CONFIG_PATH=$(pwd) DATA_PATH=$(pwd) go run cmd/main.go serve
|
||||
|
||||
## Building
|
||||
|
||||
# Generate GraphQL Models
|
||||
go run github.com/99designs/gqlgen generate
|
||||
go run main.go generate
|
||||
go run cmd/main.go generate
|
||||
|
||||
## Generate GraphQL Documentation
|
||||
# From app root
|
||||
# Generate GraphQL Documentation
|
||||
graphdoc -e http://localhost:8484/query -o ./docs/schema
|
||||
|
||||
## Server Build
|
||||
|
||||
## Flutter Build
|
||||
flutter run
|
||||
|
||||
## Generate GraphQL Flutter Models
|
||||
flutter pub run build_runner build
|
||||
|
||||
BIN
assets/imagini_full.png
Normal file
|
After Width: | Height: | Size: 142 KiB |
174
assets/imagini_full.svg
Normal file
@@ -0,0 +1,174 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="2048"
|
||||
height="2201.7515"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="1.0.2 (e86c8708, 2021-01-15)"
|
||||
sodipodi:docname="temp.svg"
|
||||
inkscape:export-filename="./Fotografia Originuum - Símbolo Logotipo - 1.0.0 - 2048x2048.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.23174669"
|
||||
inkscape:cx="2237.7535"
|
||||
inkscape:cy="935.0222"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:snap-smooth-nodes="true"
|
||||
inkscape:snap-midpoints="true"
|
||||
inkscape:snap-object-midpoints="true"
|
||||
inkscape:snap-center="true"
|
||||
inkscape:snap-global="true"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:window-width="1680"
|
||||
inkscape:window-height="997"
|
||||
inkscape:window-x="91"
|
||||
inkscape:window-y="28"
|
||||
inkscape:window-maximized="0"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:document-rotation="0">
|
||||
<sodipodi:guide
|
||||
id="guide3862"
|
||||
position="0,423.28277"
|
||||
orientation="2048.0,0" />
|
||||
<sodipodi:guide
|
||||
id="guide3864"
|
||||
position="1024,423.28277"
|
||||
orientation="2048.0,0" />
|
||||
<sodipodi:guide
|
||||
id="guide3866"
|
||||
position="2048,423.28277"
|
||||
orientation="2048.0,0" />
|
||||
<sodipodi:guide
|
||||
id="guide3868"
|
||||
position="1367.8728,-145.63908"
|
||||
orientation="0,2048.0" />
|
||||
<sodipodi:guide
|
||||
id="guide3870"
|
||||
position="0,1447.2828"
|
||||
orientation="0,2048.0" />
|
||||
<sodipodi:guide
|
||||
id="guide3872"
|
||||
position="0,2471.2828"
|
||||
orientation="0,2048.0" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs4" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
transform="translate(-256.4375,1297.5312)"
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Camada 1">
|
||||
<g
|
||||
id="g3897"
|
||||
transform="translate(0,69.535705)">
|
||||
<path
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:22.6;marker:none;enable-background:accumulate"
|
||||
d="m 1423.7287,-1367.0669 c -223.8882,0 -218.1856,238.1299 -415.169,243.0944 H 860.5756 833.6694 760.77236 461.36265 410.05314 406.61165 c -83.19648,0 -150.17415,66.9777 -150.17415,150.17418 V -8.30366 c 0,83.19648 66.97767,150.17415 150.17415,150.17415 H 2154.2633 c 83.1965,0 150.1742,-66.97767 150.1742,-150.17415 v -965.49466 c 0,-83.19648 -66.9777,-150.17418 -150.1742,-150.17418 h -170.5102 c -196.9835,-4.9645 -191.2807,-243.0944 -415.1689,-243.0944 z m -891.3462,154.5543 c -39.29917,0 -71.01985,30.2859 -71.01985,68.204 h 299.40971 c 0,-37.9181 -31.40792,-68.204 -70.707,-68.204 z"
|
||||
id="path3829"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="sccccccsssssssscsssccss" />
|
||||
<ellipse
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:#ffffff;stroke-width:50.0581;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="path3772"
|
||||
cx="1496.1152"
|
||||
cy="-483.31482"
|
||||
rx="460.15295"
|
||||
ry="460.15305" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;enable-background:accumulate"
|
||||
id="rect3797"
|
||||
width="258.54865"
|
||||
height="144.11386"
|
||||
x="1366.8821"
|
||||
y="-1317.5764"
|
||||
ry="72.056931" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
id="layer1-1"
|
||||
transform="matrix(1.7826087,0,0,1.7826087,613.92339,-1368.5121)">
|
||||
<path
|
||||
style="fill:#ef00ef;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
d="m 495.06889,306.5449 c -78.2212,0 -147.3233,39.05231 -188.875,98.71875 l 68.8437,119.28125 125.8438,-217.9375 c -1.9315,-0.0479 -3.8695,-0.0625 -5.8125,-0.0625 z"
|
||||
id="path3841"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#ff5151;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
d="m 514.31889,307.3574 -68.875,119.28125 h 251.6875 C 661.03789,360.41854 593.35419,313.91127 514.31889,307.3574 Z"
|
||||
id="path3839"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#5d5dff;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
d="m 298.81889,416.51365 c -21.4218,34.94341 -33.75,76.04095 -33.75,120.03125 0,35.02939 7.837,68.22126 21.8437,97.9375 h 137.75 z"
|
||||
id="path3837"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#ff8c41;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
d="m 565.44389,438.63865 125.8437,217.9375 c 21.4218,-34.94341 33.7813,-76.04095 33.7813,-120.03125 0,-35.01463 -7.8482,-68.1996 -21.8438,-97.90625 z"
|
||||
id="path3835"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#ffff5d;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
d="M 615.03759,548.57615 489.22509,766.4824 c 1.9418,0.0484 3.8903,0.0625 5.8438,0.0625 78.2094,0 147.2899,-39.03629 188.8437,-98.6875 z"
|
||||
id="path3833"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#5fff5f;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
d="m 293.00639,646.4824 c 36.098,66.2005 103.761,112.69668 182.7812,119.25 l 68.8438,-119.25 z"
|
||||
id="path3828"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:614.817px;line-height:1.25;font-family:sans-serif;stroke-width:3.20218"
|
||||
x="214.89394"
|
||||
y="780.23138"
|
||||
id="text455"
|
||||
transform="scale(1.0039787,0.99603708)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan453"
|
||||
x="214.89394"
|
||||
y="780.23138"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'.Keyboard';-inkscape-font-specification:'.Keyboard';stroke-width:3.20218">imagini</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.1 KiB |
BIN
assets/imagini_logo.png
Normal file
|
After Width: | Height: | Size: 164 KiB |
196
assets/imagini_logo.svg
Normal file
@@ -0,0 +1,196 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="2400"
|
||||
height="2400"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="1.0.2 (e86c8708, 2021-01-15)"
|
||||
sodipodi:docname="imagini_logo.svg"
|
||||
inkscape:export-filename="./Fotografia Originuum - Símbolo Logotipo - 1.0.0 - 2048x2048.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.23174669"
|
||||
inkscape:cx="2512.9998"
|
||||
inkscape:cy="1771.1564"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:snap-smooth-nodes="true"
|
||||
inkscape:snap-midpoints="true"
|
||||
inkscape:snap-object-midpoints="true"
|
||||
inkscape:snap-center="true"
|
||||
inkscape:snap-global="true"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:window-width="1680"
|
||||
inkscape:window-height="997"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="25"
|
||||
inkscape:window-maximized="0"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:document-rotation="0">
|
||||
<sodipodi:guide
|
||||
id="guide3862"
|
||||
position="176,176"
|
||||
orientation="2048.0,0" />
|
||||
<sodipodi:guide
|
||||
id="guide3864"
|
||||
position="1200,176"
|
||||
orientation="2048.0,0" />
|
||||
<sodipodi:guide
|
||||
id="guide3866"
|
||||
position="2224,176"
|
||||
orientation="2048.0,0" />
|
||||
<sodipodi:guide
|
||||
id="guide3868"
|
||||
position="1543.8728,-392.92185"
|
||||
orientation="0,2048.0" />
|
||||
<sodipodi:guide
|
||||
id="guide3870"
|
||||
position="176,1200"
|
||||
orientation="0,2048.0" />
|
||||
<sodipodi:guide
|
||||
id="guide3872"
|
||||
position="176,2224"
|
||||
orientation="0,2048.0" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient78">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop74" />
|
||||
<stop
|
||||
style="stop-color:#e6e6e6;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop76" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient78"
|
||||
id="radialGradient72"
|
||||
cx="1280.4375"
|
||||
cy="-543.0625"
|
||||
fx="1280.4375"
|
||||
fy="-543.0625"
|
||||
r="1200"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-1.1067567e-8,1.8164746,-1.9529083,-2.1450912e-6,219.88626,-2868.9458)" />
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
transform="translate(-80.4375,1743.0625)"
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Camada 1">
|
||||
<rect
|
||||
id="rect32"
|
||||
width="2400"
|
||||
height="2400"
|
||||
x="80.4375"
|
||||
y="-1743.0625"
|
||||
style="fill:url(#radialGradient72);stroke-width:0.9016;fill-opacity:1"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90" />
|
||||
<g
|
||||
id="g3897"
|
||||
transform="translate(0,69.535705)">
|
||||
<path
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:22.6;marker:none;enable-background:accumulate"
|
||||
d="m 1423.7287,-1367.0669 c -223.8882,0 -218.1856,238.1299 -415.169,243.0944 H 860.5756 833.6694 760.77236 461.36265 410.05314 406.61165 c -83.19648,0 -150.17415,66.9777 -150.17415,150.17418 V -8.30366 c 0,83.19648 66.97767,150.17415 150.17415,150.17415 H 2154.2633 c 83.1965,0 150.1742,-66.97767 150.1742,-150.17415 v -965.49466 c 0,-83.19648 -66.9777,-150.17418 -150.1742,-150.17418 h -170.5102 c -196.9835,-4.9645 -191.2807,-243.0944 -415.1689,-243.0944 z m -891.3462,154.5543 c -39.29917,0 -71.01985,30.2859 -71.01985,68.204 h 299.40971 c 0,-37.9181 -31.40792,-68.204 -70.707,-68.204 z"
|
||||
id="path3829"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="sccccccsssssssscsssccss" />
|
||||
<ellipse
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:#ffffff;stroke-width:50.0581;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="path3772"
|
||||
cx="1496.1152"
|
||||
cy="-483.31482"
|
||||
rx="460.15295"
|
||||
ry="460.15305" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;enable-background:accumulate"
|
||||
id="rect3797"
|
||||
width="258.54865"
|
||||
height="144.11386"
|
||||
x="1366.8821"
|
||||
y="-1317.5764"
|
||||
ry="72.056931" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
id="layer1-1"
|
||||
transform="matrix(1.7826087,0,0,1.7826087,613.92339,-1368.5121)">
|
||||
<path
|
||||
style="fill:#ef00ef;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
d="m 495.06889,306.5449 c -78.2212,0 -147.3233,39.05231 -188.875,98.71875 l 68.8437,119.28125 125.8438,-217.9375 c -1.9315,-0.0479 -3.8695,-0.0625 -5.8125,-0.0625 z"
|
||||
id="path3841"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#ff5151;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
d="m 514.31889,307.3574 -68.875,119.28125 h 251.6875 C 661.03789,360.41854 593.35419,313.91127 514.31889,307.3574 Z"
|
||||
id="path3839"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#5d5dff;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
d="m 298.81889,416.51365 c -21.4218,34.94341 -33.75,76.04095 -33.75,120.03125 0,35.02939 7.837,68.22126 21.8437,97.9375 h 137.75 z"
|
||||
id="path3837"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#ff8c41;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
d="m 565.44389,438.63865 125.8437,217.9375 c 21.4218,-34.94341 33.7813,-76.04095 33.7813,-120.03125 0,-35.01463 -7.8482,-68.1996 -21.8438,-97.90625 z"
|
||||
id="path3835"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#ffff5d;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
d="M 615.03759,548.57615 489.22509,766.4824 c 1.9418,0.0484 3.8903,0.0625 5.8438,0.0625 78.2094,0 147.2899,-39.03629 188.8437,-98.6875 z"
|
||||
id="path3833"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#5fff5f;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
d="m 293.00639,646.4824 c 36.098,66.2005 103.761,112.69668 182.7812,119.25 l 68.8438,-119.25 z"
|
||||
id="path3828"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.6 KiB |
@@ -5,6 +5,7 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/h2non/bimg"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"reichard.io/imagini/internal/api"
|
||||
@@ -44,6 +45,9 @@ func (s *Server) StartServer() {
|
||||
}
|
||||
|
||||
go func() {
|
||||
bimg.VipsCacheSetMax(0)
|
||||
bimg.VipsCacheSetMaxMem(0)
|
||||
|
||||
err := s.httpServer.ListenAndServe()
|
||||
if err != nil {
|
||||
log.Error("Error starting server ", err)
|
||||
|
||||
8
go.mod
@@ -4,21 +4,15 @@ go 1.15
|
||||
|
||||
require (
|
||||
github.com/99designs/gqlgen v0.13.0
|
||||
github.com/codeon/govips v0.0.0-20200329201227-415341c0ce33 // indirect
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/disintegration/imaging v1.6.2 // indirect
|
||||
github.com/dsoprea/go-exif/v3 v3.0.0-20201216222538-db167117f483
|
||||
github.com/gabriel-vasile/mimetype v1.1.2
|
||||
github.com/google/uuid v1.1.5
|
||||
github.com/h2non/bimg v1.1.5
|
||||
github.com/iancoleman/strcase v0.1.3
|
||||
github.com/lestrrat-go/jwx v1.0.8
|
||||
github.com/mattn/go-sqlite3 v1.14.6
|
||||
github.com/sirupsen/logrus v1.7.0
|
||||
github.com/tus/tusd v1.4.0
|
||||
github.com/urfave/cli/v2 v2.3.0
|
||||
github.com/vektah/gqlparser/v2 v2.1.0
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
|
||||
golang.org/x/image v0.0.0-20201208152932-35266b937fa6 // indirect
|
||||
gorm.io/driver/sqlite v1.1.4
|
||||
gorm.io/gorm v1.20.9
|
||||
)
|
||||
|
||||
228
go.sum
@@ -1,122 +1,44 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
cloud.google.com/go v0.40.0/go.mod h1:Tk58MuI9rbLMKlAjeO/bDnteAx7tX2gJIXw4T5Jwlro=
|
||||
github.com/99designs/gqlgen v0.13.0 h1:haLTcUp3Vwp80xMVEg5KRNwzfUrgFdRmtBY8fuB8scA=
|
||||
github.com/99designs/gqlgen v0.13.0/go.mod h1:NV130r6f4tpRWuAI+zsrSdooO/eWUv+Gyyoi3rEfXIk=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
|
||||
github.com/agnivade/levenshtein v1.0.3 h1:M5ZnqLOoZR8ygVq0FfkXsNOKzMCk0xRiow0R5+5VkQ0=
|
||||
github.com/agnivade/levenshtein v1.0.3/go.mod h1:4SFRZbbXWLF4MU1T9Qg0pGgH3Pjs+t6ie5efyrwRJXs=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
|
||||
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
|
||||
github.com/aws/aws-sdk-go v1.20.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40 h1:y4B3+GPxKlrigF1ha5FFErxK+sr6sWxQovRMzwMhejo=
|
||||
github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/codeon/govips v0.0.0-20200329201227-415341c0ce33 h1:/wmSAm0UZlQ/NmiwUlThjUUHe2cD36rjM61px1X6ccM=
|
||||
github.com/codeon/govips v0.0.0-20200329201227-415341c0ce33/go.mod h1:kXwwWC7hMGnPrV6bw8gFi2k0ZLTiYTNMM+G3D9cUBt0=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgrijalva/jwt-go v1.0.2 h1:KPldsxuKGsS2FPWsNeg9ZO18aCrGKujPoWXn2yo+KQM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c h1:TUuUh0Xgj97tLMNtWtNvI9mIV6isjEb9lBMNv+77IGM=
|
||||
github.com/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=
|
||||
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
|
||||
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
|
||||
github.com/dsoprea/go-exif v0.0.0-20201216222538-db167117f483 h1:zJb7OUzMMSul61UUhYXWNOXc9nO1lexj3jsAgoDtCqg=
|
||||
github.com/dsoprea/go-exif/v2 v2.0.0-20200321225314-640175a69fe4/go.mod h1:Lm2lMM2zx8p4a34ZemkaUV95AnMl4ZvLbCUbwOvLC2E=
|
||||
github.com/dsoprea/go-exif/v3 v3.0.0-20200717053412-08f1b6708903/go.mod h1:0nsO1ce0mh5czxGeLo4+OCZ/C6Eo6ZlMWsz7rH/Gxv8=
|
||||
github.com/dsoprea/go-exif/v3 v3.0.0-20201216222538-db167117f483 h1:rz9dPf+Unge2D5RNIRNFvCc2OrGfhAPuxx4L6412jdI=
|
||||
github.com/dsoprea/go-exif/v3 v3.0.0-20201216222538-db167117f483/go.mod h1:cg5SNYKHMmzxsr9X6ZeLh/nfBRHHp5PngtEPcujONtk=
|
||||
github.com/dsoprea/go-logging v0.0.0-20190624164917-c4f10aab7696/go.mod h1:Nm/x2ZUNRW6Fe5C3LxdY1PyZY5wmDv/s5dkPJ/VB3iA=
|
||||
github.com/dsoprea/go-logging v0.0.0-20200517223158-a10564966e9d h1:F/7L5wr/fP/SKeO5HuMlNEX9Ipyx2MbH2rV9G4zJRpk=
|
||||
github.com/dsoprea/go-logging v0.0.0-20200517223158-a10564966e9d/go.mod h1:7I+3Pe2o/YSU88W0hWlm9S22W7XI1JFNJ86U0zPKMf8=
|
||||
github.com/dsoprea/go-utility v0.0.0-20200711062821-fab8125e9bdf h1:/w4QxepU4AHh3AuO6/g8y/YIIHH5+aKP3Bj8sg5cqhU=
|
||||
github.com/dsoprea/go-utility v0.0.0-20200711062821-fab8125e9bdf/go.mod h1:95+K3z2L0mqsVYd6yveIv1lmtT3tcQQ3dVakPySffW8=
|
||||
github.com/dsoprea/go-utility/v2 v2.0.0-20200717064901-2fccff4aa15e h1:IxIbA7VbCNrwumIYjDoMOdf4KOSkMC6NJE4s8oRbE7E=
|
||||
github.com/dsoprea/go-utility/v2 v2.0.0-20200717064901-2fccff4aa15e/go.mod h1:uAzdkPTub5Y9yQwXe8W4m2XuP0tK4a9Q/dantD0+uaU=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/gabriel-vasile/mimetype v1.1.2 h1:gaPnPcNor5aZSVCJVSGipcpbgMWiAAj9z182ocSGbHU=
|
||||
github.com/gabriel-vasile/mimetype v1.1.2/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To=
|
||||
github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
|
||||
github.com/go-errors/errors v1.1.1 h1:ljK/pL5ltg3qoN+OtN6yCv9HWSfMwxSx90GJCZQxYNg=
|
||||
github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-macaron/gzip v0.0.0-20200329073552-98214d7a897e h1:PlmAvovRGUTW15weOGR3gny33PCUL2Ko65rN1w1XBog=
|
||||
github.com/go-macaron/gzip v0.0.0-20200329073552-98214d7a897e/go.mod h1:1if9hBU2ZPlrmuwN27VIn11Ur9OXBiZDLDPmCKbb7N4=
|
||||
github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191 h1:NjHlg70DuOkcAMqgt0+XA+NHwtu66MkTVVgR4fFWbcI=
|
||||
github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191/go.mod h1:VFI2o2q9kYsC4o7VP1HrEVosiZZTd+MVT3YZx4gqvJw=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
|
||||
github.com/golang/geo v0.0.0-20200319012246-673a6f80352d h1:C/hKUcHT483btRbeGkrRjJz+Zbcj8audldIi9tRJDCc=
|
||||
github.com/golang/geo v0.0.0-20200319012246-673a6f80352d/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/uuid v1.1.5 h1:kxhtnfFVi+rYdOALN0B3k9UT86zVJKfBimRaciULW4I=
|
||||
github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE=
|
||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
|
||||
github.com/h2non/bimg v1.1.5 h1:o3xsUBxM8s7+e7PmpiWIkEYdeYayJ94eh4cJLx67m1k=
|
||||
github.com/h2non/bimg v1.1.5/go.mod h1:R3+UiYwkK4rQl6KVFTOFJHitgLbZXBZNFh2cv3AEbp8=
|
||||
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/iancoleman/strcase v0.1.3 h1:dJBk1m2/qjL1twPLf68JND55vvivMupZ4wIzE8CTdBw=
|
||||
github.com/iancoleman/strcase v0.1.3/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.1 h1:g39TucaRWyV3dwDO++eEc6qf8TVIQ/Da48WmqjZ3i7E=
|
||||
github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.10.3 h1:OP96hzwJVBIHYU52pVTI6CczrxPvrGfgqF9N5eTO0Q8=
|
||||
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lestrrat-go/backoff/v2 v2.0.3 h1:2ABaTa5ifB1L90aoRMjaPa97p0WzzVe93Vggv8oZftw=
|
||||
github.com/lestrrat-go/backoff/v2 v2.0.3/go.mod h1:mU93bMXuG27/Y5erI5E9weqavpTX5qiVFZI4uXAX0xk=
|
||||
@@ -128,6 +50,7 @@ github.com/lestrrat-go/jwx v1.0.8 h1:Mj/2Ey9rkGx4w5IMQ2Q+9KLZn4cZoMgKrnMxi9eXE3k
|
||||
github.com/lestrrat-go/jwx v1.0.8/go.mod h1:6XJ5sxHF5U116AxYxeHfTnfsZRMgmeKY214zwZDdvho=
|
||||
github.com/lestrrat-go/option v0.0.0-20210103042652-6f1ecfceda35 h1:lea8Wt+1ePkVrI2/WD+NgQT5r/XsLAzxeqtyFLcEs10=
|
||||
github.com/lestrrat-go/option v0.0.0-20210103042652-6f1ecfceda35/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||
github.com/lestrrat-go/pdebug/v3 v3.0.0-20210111091911-ec4f5c88c087 h1:T5Wh8C/p5nWoGuEUBQj+daEXkj1CScB9GshvvsBJhpg=
|
||||
github.com/lestrrat-go/pdebug/v3 v3.0.0-20210111091911-ec4f5c88c087/go.mod h1:za+m+Ve24yCxTEhR59N7UlnJomWwCiIqbJRmKeiADU4=
|
||||
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007 h1:reVOUXwnhsYv/8UqjvhrMOu5CNT9UapHFLbQ2JcXsmg=
|
||||
@@ -135,65 +58,35 @@ github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007/go.mod h1:9ELz6aaclSIG
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-sqlite3 v1.14.5 h1:1IdxlwTNazvbKJQSxoJ5/9ECbEeaTTyeU7sEAZ5KKTQ=
|
||||
github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
|
||||
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
|
||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047 h1:zCoDWFD5nrJJVjbXiDZcVhOBSzKn3o9LgRLLMRNuru8=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
|
||||
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
||||
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sethgrid/pester v0.0.0-20190127155807-68a33a018ad0/go.mod h1:Ad7IjTpvzZO8Fl0vh9AzQ+j/jYZfyp2diGwI8m5q+ns=
|
||||
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
|
||||
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/tus/tusd v1.4.0 h1:8+TmY/Ip2mxO3UlYzrqUkQWMd/FmSSdcIrlJHrr+3HQ=
|
||||
github.com/tus/tusd v1.4.0/go.mod h1:ygrT4B9ZSb27dx3uTnobX5nOFDnutBL6iWKLH4+KpA0=
|
||||
github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e h1:GSGeB9EAKY2spCABz6xOX5DbxZEXolK+nBSvmsQwRjM=
|
||||
github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM=
|
||||
github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU=
|
||||
github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
|
||||
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
|
||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||
@@ -201,88 +94,33 @@ github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e h1:+w0Zm/9gaWp
|
||||
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=
|
||||
github.com/vektah/gqlparser/v2 v2.1.0 h1:uiKJ+T5HMGGQM2kRKQ8Pxw8+Zq9qhhZhz/lieYvCMns=
|
||||
github.com/vektah/gqlparser/v2 v2.1.0/go.mod h1:SyUiHgLATUR8BiYURfTirrTcGpcE+4XkV2se04Px1Ms=
|
||||
github.com/vimeo/go-util v1.2.0/go.mod h1:s13SMDTSO7AjH1nbgp707mfN5JFIWUFDU5MDDuRRtKs=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U=
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20201208152932-35266b937fa6 h1:nfeHNc1nAqecKCy2FCy4HY+soOOe5sDLJ/gZLbx6GYI=
|
||||
golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120 h1:EZ3cVSzKOlJxAd8e8YAJ7no8nNypTxexh/YE/xW3ZEY=
|
||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200417140056-c07e33ef3290 h1:NXNmtp0ToD36cui5IqWy95LC4Y6vT/4y3RnPxlQPinU=
|
||||
@@ -291,49 +129,19 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.6.0/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||
gopkg.in/Acconut/lockfile.v1 v1.1.0/go.mod h1:6UCz3wJ8tSFUsPR6uP/j8uegEtDuEEqFxlpi0JI4Umw=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/h2non/gock.v1 v1.0.14/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE=
|
||||
gopkg.in/ini.v1 v1.46.0 h1:VeDZbLYGaupuvIrsYCEOe/L/2Pcs5n7hdO1ZTjporag=
|
||||
gopkg.in/ini.v1 v1.46.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/macaron.v1 v1.3.5/go.mod h1:uMZCFccv9yr5TipIalVOyAyZQuOH3OkmXvgcWwhJuP4=
|
||||
gopkg.in/macaron.v1 v1.4.0 h1:RJHC09fAnQ8tuGUiZNjG0uyL1BWSdSWd9SpufIcEArQ=
|
||||
gopkg.in/macaron.v1 v1.4.0/go.mod h1:uMZCFccv9yr5TipIalVOyAyZQuOH3OkmXvgcWwhJuP4=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/sqlite v1.1.4 h1:PDzwYE+sI6De2+mxAneV9Xs11+ZyKV6oxD3wDGkaNvM=
|
||||
gorm.io/driver/sqlite v1.1.4/go.mod h1:mJCeTFr7+crvS+TRnWc5Z3UvwxUN1BGBLMrf5LA9DYw=
|
||||
gorm.io/gorm v1.20.7/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
|
||||
gorm.io/gorm v1.20.9 h1:M3aIZKXAC1PtPVu9t3WGwkBTE1le5c2telz3I/qjRNg=
|
||||
gorm.io/gorm v1.20.9/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
sourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
||||
sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k=
|
||||
|
||||
@@ -87,6 +87,7 @@ type ComplexityRoot struct {
|
||||
CreatedAt func(childComplexity int) int
|
||||
ExifDate func(childComplexity int) int
|
||||
FileName func(childComplexity int) int
|
||||
Height func(childComplexity int) int
|
||||
ID func(childComplexity int) int
|
||||
IsVideo func(childComplexity int) int
|
||||
Latitude func(childComplexity int) int
|
||||
@@ -95,6 +96,7 @@ type ComplexityRoot struct {
|
||||
Tags func(childComplexity int) int
|
||||
UpdatedAt func(childComplexity int) int
|
||||
UserID func(childComplexity int) int
|
||||
Width func(childComplexity int) int
|
||||
}
|
||||
|
||||
MediaItemResponse struct {
|
||||
@@ -363,6 +365,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.MediaItem.FileName(childComplexity), true
|
||||
|
||||
case "MediaItem.height":
|
||||
if e.complexity.MediaItem.Height == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.MediaItem.Height(childComplexity), true
|
||||
|
||||
case "MediaItem.id":
|
||||
if e.complexity.MediaItem.ID == nil {
|
||||
break
|
||||
@@ -419,6 +428,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.MediaItem.UserID(childComplexity), true
|
||||
|
||||
case "MediaItem.width":
|
||||
if e.complexity.MediaItem.Width == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.MediaItem.Width(childComplexity), true
|
||||
|
||||
case "MediaItemResponse.data":
|
||||
if e.complexity.MediaItemResponse.Data == nil {
|
||||
break
|
||||
@@ -1019,6 +1035,8 @@ type MediaItem {
|
||||
isVideo: Boolean! @meta(gorm: "default:false;not null")
|
||||
fileName: String! @meta(gorm: "not null")
|
||||
origName: String! @meta(gorm: "not null")
|
||||
width: Int! @meta(gorm: "not null")
|
||||
height: Int! @meta(gorm: "not null")
|
||||
tags: [Tag] @meta(gorm: "many2many:media_tags;foreignKey:ID,UserID;References:ID")
|
||||
albums: [Album] @meta(gorm: "many2many:media_albums;foreignKey:ID,UserID;Refrences:ID")
|
||||
userID: ID! @meta(gorm: "not null")
|
||||
@@ -2937,6 +2955,124 @@ func (ec *executionContext) _MediaItem_origName(ctx context.Context, field graph
|
||||
return ec.marshalNString2string(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _MediaItem_width(ctx context.Context, field graphql.CollectedField, obj *model.MediaItem) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "MediaItem",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
directive0 := func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Width, nil
|
||||
}
|
||||
directive1 := func(ctx context.Context) (interface{}, error) {
|
||||
gorm, err := ec.unmarshalOString2ᚖstring(ctx, "not null")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ec.directives.Meta == nil {
|
||||
return nil, errors.New("directive meta is not implemented")
|
||||
}
|
||||
return ec.directives.Meta(ctx, obj, directive0, gorm)
|
||||
}
|
||||
|
||||
tmp, err := directive1(rctx)
|
||||
if err != nil {
|
||||
return nil, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
if tmp == nil {
|
||||
return nil, nil
|
||||
}
|
||||
if data, ok := tmp.(int); ok {
|
||||
return data, nil
|
||||
}
|
||||
return nil, fmt.Errorf(`unexpected type %T from directive, should be int`, tmp)
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(int)
|
||||
fc.Result = res
|
||||
return ec.marshalNInt2int(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _MediaItem_height(ctx context.Context, field graphql.CollectedField, obj *model.MediaItem) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "MediaItem",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
directive0 := func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Height, nil
|
||||
}
|
||||
directive1 := func(ctx context.Context) (interface{}, error) {
|
||||
gorm, err := ec.unmarshalOString2ᚖstring(ctx, "not null")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ec.directives.Meta == nil {
|
||||
return nil, errors.New("directive meta is not implemented")
|
||||
}
|
||||
return ec.directives.Meta(ctx, obj, directive0, gorm)
|
||||
}
|
||||
|
||||
tmp, err := directive1(rctx)
|
||||
if err != nil {
|
||||
return nil, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
if tmp == nil {
|
||||
return nil, nil
|
||||
}
|
||||
if data, ok := tmp.(int); ok {
|
||||
return data, nil
|
||||
}
|
||||
return nil, fmt.Errorf(`unexpected type %T from directive, should be int`, tmp)
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(int)
|
||||
fc.Result = res
|
||||
return ec.marshalNInt2int(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _MediaItem_tags(ctx context.Context, field graphql.CollectedField, obj *model.MediaItem) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
@@ -7615,6 +7751,16 @@ func (ec *executionContext) _MediaItem(ctx context.Context, sel ast.SelectionSet
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "width":
|
||||
out.Values[i] = ec._MediaItem_width(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "height":
|
||||
out.Values[i] = ec._MediaItem_height(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "tags":
|
||||
out.Values[i] = ec._MediaItem_tags(ctx, field, obj)
|
||||
case "albums":
|
||||
|
||||
@@ -4,12 +4,13 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/dsoprea/go-exif/v3"
|
||||
exifcommon "github.com/dsoprea/go-exif/v3/common"
|
||||
"github.com/google/uuid"
|
||||
"github.com/h2non/bimg"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"reichard.io/imagini/graph/model"
|
||||
)
|
||||
|
||||
@@ -76,45 +77,50 @@ func deriveDeviceType(r *http.Request) model.DeviceType {
|
||||
return model.DeviceTypeUnknown
|
||||
}
|
||||
|
||||
func mediaItemFromEXIFData(filePath string) (*model.MediaItem, error) {
|
||||
rawExif, err := exif.SearchFileAndExtractExif(filePath)
|
||||
entries, _, err := exif.GetFlatExifData(rawExif, nil)
|
||||
|
||||
decLong := float64(1)
|
||||
decLat := float64(1)
|
||||
|
||||
func mediaItemFromEXIF(meta bimg.EXIF) *model.MediaItem {
|
||||
mediaItem := &model.MediaItem{}
|
||||
for _, v := range entries {
|
||||
if v.TagName == "DateTimeOriginal" {
|
||||
formattedTime, _ := time.Parse("2006:01:02 15:04:05", v.Formatted)
|
||||
|
||||
// DateTimeOriginal
|
||||
formattedTime, _ := time.Parse("2006:01:02 15:04:05", meta.DateTimeOriginal)
|
||||
mediaItem.ExifDate = &formattedTime
|
||||
} else if v.TagName == "GPSLatitude" {
|
||||
latStruct := v.Value.([]exifcommon.Rational)
|
||||
decLat *= deriveDecimalCoordinate(
|
||||
latStruct[0].Numerator/latStruct[0].Denominator,
|
||||
latStruct[1].Numerator/latStruct[1].Denominator,
|
||||
float64(latStruct[2].Numerator)/float64(latStruct[2].Denominator),
|
||||
)
|
||||
} else if v.TagName == "GPSLongitude" {
|
||||
longStruct := v.Value.([]exifcommon.Rational)
|
||||
decLong *= deriveDecimalCoordinate(
|
||||
longStruct[0].Numerator/longStruct[0].Denominator,
|
||||
longStruct[1].Numerator/longStruct[1].Denominator,
|
||||
float64(longStruct[2].Numerator)/float64(longStruct[2].Denominator),
|
||||
)
|
||||
} else if v.TagName == "GPSLatitudeRef" && v.Formatted == "S" {
|
||||
decLat *= -1
|
||||
} else if v.TagName == "GPSLongitudeRef" && v.Formatted == "W" {
|
||||
decLong *= -1
|
||||
}
|
||||
|
||||
// GPSLatitude / Ref
|
||||
mediaItem.Latitude = deriveDecimalCoordinate(meta.GPSLatitude, meta.GPSLatitudeRef)
|
||||
|
||||
// GPSLongitude / Ref
|
||||
mediaItem.Longitude = deriveDecimalCoordinate(meta.GPSLongitude, meta.GPSLongitudeRef)
|
||||
|
||||
return mediaItem
|
||||
}
|
||||
|
||||
mediaItem.Latitude = &decLat
|
||||
mediaItem.Longitude = &decLong
|
||||
func deriveDecimalCoordinate(coords, direction string) *float64 {
|
||||
divideBy := [3]float64{1, 60, 3600}
|
||||
var calculatedResult float64
|
||||
|
||||
return mediaItem, err
|
||||
splitCoords := strings.Split(coords, " ")
|
||||
if len(splitCoords) != 3 {
|
||||
return nil
|
||||
}
|
||||
|
||||
func deriveDecimalCoordinate(degrees, minutes uint32, seconds float64) float64 {
|
||||
return float64(degrees) + (float64(minutes) / 60) + (seconds / 3600)
|
||||
for i := 0; i < len(splitCoords); i++ {
|
||||
splitSection := strings.Split(splitCoords[i], "/")
|
||||
numerator, err := strconv.ParseFloat(splitSection[0], 64)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
denominator, err := strconv.ParseFloat(splitSection[1], 64)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
calculatedResult += numerator / denominator / divideBy[i]
|
||||
}
|
||||
|
||||
if direction == "S" {
|
||||
calculatedResult *= -1
|
||||
} else if direction == "W" {
|
||||
calculatedResult *= -1
|
||||
}
|
||||
|
||||
log.Info(calculatedResult)
|
||||
return &calculatedResult
|
||||
}
|
||||
|
||||
@@ -108,6 +108,8 @@ type MediaItem struct {
|
||||
IsVideo bool `json:"isVideo" gorm:"default:false;not null"`
|
||||
FileName string `json:"fileName" gorm:"not null"`
|
||||
OrigName string `json:"origName" gorm:"not null"`
|
||||
Width int `json:"width" gorm:"not null"`
|
||||
Height int `json:"height" gorm:"not null"`
|
||||
Tags []*Tag `json:"tags" gorm:"many2many:media_tags;foreignKey:ID,UserID;References:ID"`
|
||||
Albums []*Album `json:"albums" gorm:"many2many:media_albums;foreignKey:ID,UserID;Refrences:ID"`
|
||||
UserID string `json:"userID" gorm:"not null"`
|
||||
|
||||
@@ -158,6 +158,8 @@ type MediaItem {
|
||||
isVideo: Boolean! @meta(gorm: "default:false;not null")
|
||||
fileName: String! @meta(gorm: "not null")
|
||||
origName: String! @meta(gorm: "not null")
|
||||
width: Int! @meta(gorm: "not null")
|
||||
height: Int! @meta(gorm: "not null")
|
||||
tags: [Tag] @meta(gorm: "many2many:media_tags;foreignKey:ID,UserID;References:ID")
|
||||
albums: [Album] @meta(gorm: "many2many:media_albums;foreignKey:ID,UserID;Refrences:ID")
|
||||
userID: ID! @meta(gorm: "not null")
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
@@ -16,6 +17,8 @@ import (
|
||||
|
||||
"github.com/gabriel-vasile/mimetype"
|
||||
"github.com/google/uuid"
|
||||
"github.com/h2non/bimg"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"reichard.io/imagini/graph/generated"
|
||||
"reichard.io/imagini/graph/model"
|
||||
)
|
||||
@@ -32,6 +35,7 @@ func (r *mutationResolver) CreateMediaItem(ctx context.Context, input model.NewM
|
||||
|
||||
// Copy headers into the buffer
|
||||
if _, err := input.File.File.Read(fileHeader); err != nil {
|
||||
log.Error("[upload] Failed to read file header:", err)
|
||||
return nil, errors.New("Upload Failed")
|
||||
}
|
||||
|
||||
@@ -42,8 +46,12 @@ func (r *mutationResolver) CreateMediaItem(ctx context.Context, input model.NewM
|
||||
if strings.HasPrefix(contentType, "image/") {
|
||||
isVideo = false
|
||||
} else if strings.HasPrefix(contentType, "video/") {
|
||||
isVideo = true
|
||||
// TODO
|
||||
log.Error("[upload] Video unsupported at this time")
|
||||
return nil, errors.New("Upload Failed")
|
||||
// isVideo = true
|
||||
} else {
|
||||
log.Error("[upload] File is neither an image or video")
|
||||
return nil, errors.New("Upload Failed")
|
||||
}
|
||||
|
||||
@@ -55,28 +63,49 @@ func (r *mutationResolver) CreateMediaItem(ctx context.Context, input model.NewM
|
||||
filePath := path.Join(folderPath + "/" + fileName)
|
||||
|
||||
// Create File
|
||||
f, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0600)
|
||||
f, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE, 0600)
|
||||
if err != nil {
|
||||
log.Error("[upload] Unable to open file handle:", err)
|
||||
return nil, errors.New("Upload Failed")
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
// Copy header to file
|
||||
_, err = io.Copy(f, bytes.NewReader(fileHeader))
|
||||
// Concat File
|
||||
concatFile := io.MultiReader(bytes.NewReader(fileHeader), input.File.File)
|
||||
|
||||
// Copy file
|
||||
_, err = io.Copy(f, concatFile)
|
||||
if err != nil {
|
||||
log.Error("[upload] Unable to copy file:", err)
|
||||
return nil, errors.New("Upload Failed")
|
||||
}
|
||||
|
||||
// Copy remaining file
|
||||
_, err = io.Copy(f, input.File.File)
|
||||
// Load Image
|
||||
f.Seek(0, io.SeekStart)
|
||||
buffer, err := ioutil.ReadAll(f)
|
||||
newImage := bimg.NewImage(buffer)
|
||||
|
||||
// Create MediaItem from EXIF
|
||||
meta, err := newImage.Metadata()
|
||||
if err != nil {
|
||||
log.Error("[upload] Unable to extract metadata:", err)
|
||||
return nil, errors.New("Upload Failed")
|
||||
}
|
||||
mediaItem := mediaItemFromEXIF(meta.EXIF)
|
||||
|
||||
// Determine Image Size
|
||||
imageSize, err := newImage.Size()
|
||||
if err != nil {
|
||||
log.Error("[upload] Unable to extract dimension data:", err)
|
||||
return nil, errors.New("Upload Failed")
|
||||
}
|
||||
|
||||
// Create MediaItem From EXIF Data
|
||||
mediaItem, err := mediaItemFromEXIFData(filePath)
|
||||
if err != nil {
|
||||
return nil, errors.New("Upload Failed")
|
||||
if meta.Orientation > 4 {
|
||||
mediaItem.Width = imageSize.Height
|
||||
mediaItem.Height = imageSize.Width
|
||||
} else {
|
||||
mediaItem.Width = imageSize.Width
|
||||
mediaItem.Height = imageSize.Height
|
||||
}
|
||||
|
||||
// Add Additional MediaItem Fields
|
||||
@@ -89,6 +118,7 @@ func (r *mutationResolver) CreateMediaItem(ctx context.Context, input model.NewM
|
||||
// Create MediaItem in DB
|
||||
err = r.DB.CreateMediaItem(mediaItem)
|
||||
if err != nil {
|
||||
log.Error("[upload] Unable to populate create file in DB:", err)
|
||||
return nil, errors.New("Upload Failed")
|
||||
}
|
||||
|
||||
|
||||
5
init_pkg_config_path
Executable file
@@ -0,0 +1,5 @@
|
||||
# nix-env -i vips
|
||||
PKG1=$(find /nix/store/*/lib/pkgconfig/* -name 'vips.pc' | sed 's/vips\.pc$//')
|
||||
PKG2=$(find /nix/store/*/lib/pkgconfig/* -name 'gobject-2.0.pc' | sed 's/gobject-2.0\.pc$//')
|
||||
|
||||
export PKG_CONFIG_PATH=$PKG1:$PKG2
|
||||
@@ -41,35 +41,46 @@ func (api *API) refreshTokens(refreshToken jwt.Token) (string, string, error) {
|
||||
}
|
||||
|
||||
// Update Access Token
|
||||
accessTokenCookie, err := api.Auth.CreateJWTAccessToken(user, device)
|
||||
accessToken, err := api.Auth.CreateJWTAccessToken(user, device)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
return accessTokenCookie, "", err
|
||||
return accessToken, "", err
|
||||
}
|
||||
|
||||
func (api *API) validateTokens(w *http.ResponseWriter, r *http.Request) (jwt.Token, error) {
|
||||
// TODO: Check from X-Imagini-AccessToken
|
||||
// TODO: Check from X-Imagini-RefreshToken
|
||||
|
||||
// Validate Access Token
|
||||
accessCookie, _ := r.Cookie("AccessToken")
|
||||
if accessCookie != nil {
|
||||
accessToken, err := api.Auth.ValidateJWTAccessToken(accessCookie.Value)
|
||||
accessTokenHeader := r.Header.Get("X-Imagini-AccessToken")
|
||||
if accessTokenHeader != "" {
|
||||
accessToken, err := api.Auth.ValidateJWTAccessToken(accessTokenHeader)
|
||||
if err == nil {
|
||||
return accessToken, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Validate Refresh Cookie Exists
|
||||
refreshCookie, _ := r.Cookie("RefreshToken")
|
||||
if refreshCookie == nil {
|
||||
refreshTokenHeader := r.Header.Get("X-Imagini-RefreshToken")
|
||||
if refreshTokenHeader == "" {
|
||||
return nil, errors.New("Tokens Invalid")
|
||||
}
|
||||
|
||||
// Validate Access Token
|
||||
// accessCookie, _ := r.Cookie("AccessToken")
|
||||
// if accessCookie != nil {
|
||||
// accessToken, err := api.Auth.ValidateJWTAccessToken(accessCookie.Value)
|
||||
// if err == nil {
|
||||
// return accessToken, nil
|
||||
// }
|
||||
// }
|
||||
|
||||
// Validate Refresh Cookie Exists
|
||||
// refreshCookie, _ := r.Cookie("RefreshToken")
|
||||
// if refreshCookie == nil {
|
||||
// return nil, errors.New("Tokens Invalid")
|
||||
// }
|
||||
|
||||
// Validate Refresh Token
|
||||
refreshToken, err := api.Auth.ValidateJWTRefreshToken(refreshCookie.Value)
|
||||
// refreshToken, err := api.Auth.ValidateJWTRefreshToken(refreshCookie.Value)
|
||||
refreshToken, err := api.Auth.ValidateJWTRefreshToken(refreshTokenHeader)
|
||||
if err != nil {
|
||||
return nil, errors.New("Tokens Invalid")
|
||||
}
|
||||
@@ -81,21 +92,21 @@ func (api *API) validateTokens(w *http.ResponseWriter, r *http.Request) (jwt.Tok
|
||||
}
|
||||
|
||||
// TODO: Actually Refresh Refresh Token
|
||||
newRefreshToken = refreshCookie.Value
|
||||
// newRefreshToken = refreshCookie.Value
|
||||
newRefreshToken = refreshTokenHeader
|
||||
|
||||
// Set appropriate cookies (TODO: Only for web!)
|
||||
|
||||
// Update Access & Refresh Cookies
|
||||
http.SetCookie(*w, &http.Cookie{
|
||||
Name: "AccessToken",
|
||||
Value: newAccessToken,
|
||||
})
|
||||
http.SetCookie(*w, &http.Cookie{
|
||||
Name: "RefreshToken",
|
||||
Value: newRefreshToken,
|
||||
})
|
||||
// http.SetCookie(*w, &http.Cookie{
|
||||
// Name: "AccessToken",
|
||||
// Value: newAccessToken,
|
||||
// })
|
||||
// http.SetCookie(*w, &http.Cookie{
|
||||
// Name: "RefreshToken",
|
||||
// Value: newRefreshToken,
|
||||
// })
|
||||
|
||||
// Only for iOS & Android (TODO: Remove for web! Only cause affected by CORS during development)
|
||||
(*w).Header().Set("X-Imagini-AccessToken", newAccessToken)
|
||||
(*w).Header().Set("X-Imagini-RefreshToken", newRefreshToken)
|
||||
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/h2non/bimg"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"reichard.io/imagini/graph/model"
|
||||
)
|
||||
|
||||
@@ -23,15 +29,7 @@ func (api *API) mediaHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// Acquire Width & Height Parameters
|
||||
query := r.URL.Query()
|
||||
width := query["width"]
|
||||
height := query["height"]
|
||||
_ = width
|
||||
_ = height
|
||||
|
||||
// TODO: Caching & Resizing
|
||||
// - If both, force resize with new scale
|
||||
// - If one, scale resize proportionally
|
||||
width, _ := strconv.Atoi(r.URL.Query().Get("width"))
|
||||
|
||||
// Pull out userID
|
||||
authContext := r.Context().Value("auth").(*model.AuthContext)
|
||||
@@ -46,10 +44,55 @@ func (api *API) mediaHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// Check if File Exists
|
||||
_, err := os.Stat(mediaPath)
|
||||
if os.IsNotExist(err) {
|
||||
// TODO: Different HTTP Response Code?
|
||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||
log.Warn("[media] Image does not exist on disk")
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.ServeFile(w, r, mediaPath)
|
||||
mediaFile, err := resizeAndConvertImageBIMG(mediaPath, width)
|
||||
//mediaFile, err := resizeAndConvertImage(mediaPath, width)
|
||||
if err != nil {
|
||||
log.Warn("[media] Image conversion failed:", err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: Cache mediaFile
|
||||
|
||||
http.ServeContent(w, r, fileName, time.Time{}, bytes.NewReader(mediaFile))
|
||||
}
|
||||
|
||||
func resizeAndConvertImageBIMG(path string, desiredWidth int) ([]byte, error) {
|
||||
buffer, err := bimg.Read(path)
|
||||
if err != nil {
|
||||
return nil, errors.New("[media] Unable to read image")
|
||||
}
|
||||
inputImage := bimg.NewImage(buffer)
|
||||
|
||||
// Return RAW
|
||||
if inputImage.Type() == "jpeg" && desiredWidth == 0 {
|
||||
return buffer, nil
|
||||
}
|
||||
|
||||
imageSize, err := inputImage.Size()
|
||||
|
||||
options := bimg.Options{
|
||||
Quality: 100,
|
||||
// NoAutoRotate: true,
|
||||
Background: bimg.Color{R: 255, G: 255, B: 255},
|
||||
}
|
||||
|
||||
// Set dimensions
|
||||
if desiredWidth != 0 && imageSize.Width > desiredWidth {
|
||||
options.Width = desiredWidth
|
||||
options.Quality = 50
|
||||
}
|
||||
|
||||
// Convert to JPEG
|
||||
if inputImage.Type() != "jpeg" {
|
||||
options.Type = bimg.JPEG
|
||||
}
|
||||
|
||||
// Process image
|
||||
return inputImage.Process(options)
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
package api
|
||||
@@ -52,6 +52,20 @@ func (api *API) queryMiddleware(next http.Handler) http.Handler {
|
||||
**/
|
||||
func (api *API) authMiddleware(next http.Handler) http.HandlerFunc {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// TODO: REMOVE (SOME OF) THIS!! Only for developement due to CORS
|
||||
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
//w.Header().Set("Access-Control-Expose-Headers", "*")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "x-imagini-accesstoken,x-imagini-refreshtoken")
|
||||
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
|
||||
|
||||
// CORS Preflight
|
||||
if r.Method == http.MethodOptions {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
return
|
||||
}
|
||||
|
||||
// Validate Tokens
|
||||
accessToken, err := api.validateTokens(&w, r)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,16 +1,30 @@
|
||||
# imagini
|
||||
# Imagini Client
|
||||
A cross platform (iOS, Android, & Web) client used with the Imagini server.
|
||||
|
||||
A new Flutter project.
|
||||
## Features / Roadmap
|
||||
- [DONE] Login w/ errors
|
||||
- [DONE] GraphQL client
|
||||
- [DONE] Load & tile images for user
|
||||
- [DONE] Access & Refresh Token secure storage (`localStorage` web -_-)
|
||||
|
||||
## Getting Started
|
||||
- [TODO] ALL the tests
|
||||
- [TODO] Pagination and lazy scroll load
|
||||
- [TODO] File picker upload
|
||||
- [TODO] Sync upload (Android & iOS)
|
||||
- [TODO] Image caching (Android & iOS)
|
||||
- [TODO] Lots more... TBD
|
||||
|
||||
This project is a starting point for a Flutter application.
|
||||
|
||||
A few resources to get you started if this is your first Flutter project:
|
||||
## Running
|
||||
|
||||
- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
|
||||
- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
|
||||
# Chrome
|
||||
flutter run -d chrome
|
||||
|
||||
For help getting started with Flutter, view our
|
||||
[online documentation](https://flutter.dev/docs), which offers tutorials,
|
||||
samples, guidance on mobile development, and a full API reference.
|
||||
# Simulator
|
||||
open -a Simulator
|
||||
flutter run
|
||||
|
||||
## Building
|
||||
|
||||
# Generate GraphQL Flutter Models
|
||||
flutter pub run build_runner build
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package="com.reichard.imagini">
|
||||
<application
|
||||
android:label="Imagini"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
android:icon="@mipmap/launcher_icon">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 9.8 KiB |
BIN
web_native/assets/icon/icon.png
Normal file
|
After Width: | Height: | Size: 164 KiB |
BIN
web_native/assets/imagini_full.png
Normal file
|
After Width: | Height: | Size: 142 KiB |
20
web_native/graphql/mediaItems.graphql
Normal file
@@ -0,0 +1,20 @@
|
||||
query mediaItems($order: Order, $page: Page, $filter: MediaItemFilter) {
|
||||
mediaItems(filter: $filter, page: $page, order: $order) {
|
||||
data {
|
||||
id
|
||||
fileName
|
||||
latitude
|
||||
longitude
|
||||
isVideo
|
||||
width
|
||||
height
|
||||
origName
|
||||
createdAt
|
||||
}
|
||||
page {
|
||||
size
|
||||
page
|
||||
total
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,92 +1,58 @@
|
||||
PODS:
|
||||
- DKImagePickerController/Core (4.3.2):
|
||||
- DKImagePickerController/ImageDataManager
|
||||
- DKImagePickerController/Resource
|
||||
- DKImagePickerController/ImageDataManager (4.3.2)
|
||||
- DKImagePickerController/PhotoGallery (4.3.2):
|
||||
- DKImagePickerController/Core
|
||||
- DKPhotoGallery
|
||||
- DKImagePickerController/Resource (4.3.2)
|
||||
- DKPhotoGallery (0.0.17):
|
||||
- DKPhotoGallery/Core (= 0.0.17)
|
||||
- DKPhotoGallery/Model (= 0.0.17)
|
||||
- DKPhotoGallery/Preview (= 0.0.17)
|
||||
- DKPhotoGallery/Resource (= 0.0.17)
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Core (0.0.17):
|
||||
- DKPhotoGallery/Model
|
||||
- DKPhotoGallery/Preview
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Model (0.0.17):
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Preview (0.0.17):
|
||||
- DKPhotoGallery/Model
|
||||
- DKPhotoGallery/Resource
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Resource (0.0.17):
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- file_picker (0.0.1):
|
||||
- DKImagePickerController/PhotoGallery
|
||||
- connectivity (0.0.1):
|
||||
- Flutter
|
||||
- Reachability
|
||||
- Flutter (1.0.0)
|
||||
- flutter_secure_storage (3.3.1):
|
||||
- Flutter
|
||||
- FMDB (2.7.5):
|
||||
- FMDB/standard (= 2.7.5)
|
||||
- FMDB/standard (2.7.5)
|
||||
- integration_test (0.0.1):
|
||||
- Flutter
|
||||
- SDWebImage (5.10.2):
|
||||
- SDWebImage/Core (= 5.10.2)
|
||||
- SDWebImage/Core (5.10.2)
|
||||
- shared_preferences (0.0.1):
|
||||
- path_provider (0.0.1):
|
||||
- Flutter
|
||||
- SwiftyGif (5.3.0)
|
||||
- url_launcher (0.0.1):
|
||||
- Reachability (3.2)
|
||||
- sqflite (0.0.2):
|
||||
- Flutter
|
||||
- FMDB (>= 2.7.5)
|
||||
|
||||
DEPENDENCIES:
|
||||
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||
- connectivity (from `.symlinks/plugins/connectivity/ios`)
|
||||
- Flutter (from `Flutter`)
|
||||
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
||||
- integration_test (from `.symlinks/plugins/integration_test/ios`)
|
||||
- shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
|
||||
- url_launcher (from `.symlinks/plugins/url_launcher/ios`)
|
||||
- path_provider (from `.symlinks/plugins/path_provider/ios`)
|
||||
- sqflite (from `.symlinks/plugins/sqflite/ios`)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- DKImagePickerController
|
||||
- DKPhotoGallery
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- FMDB
|
||||
- Reachability
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
file_picker:
|
||||
:path: ".symlinks/plugins/file_picker/ios"
|
||||
connectivity:
|
||||
:path: ".symlinks/plugins/connectivity/ios"
|
||||
Flutter:
|
||||
:path: Flutter
|
||||
flutter_secure_storage:
|
||||
:path: ".symlinks/plugins/flutter_secure_storage/ios"
|
||||
integration_test:
|
||||
:path: ".symlinks/plugins/integration_test/ios"
|
||||
shared_preferences:
|
||||
:path: ".symlinks/plugins/shared_preferences/ios"
|
||||
url_launcher:
|
||||
:path: ".symlinks/plugins/url_launcher/ios"
|
||||
path_provider:
|
||||
:path: ".symlinks/plugins/path_provider/ios"
|
||||
sqflite:
|
||||
:path: ".symlinks/plugins/sqflite/ios"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
DKImagePickerController: b5eb7f7a388e4643264105d648d01f727110fc3d
|
||||
DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179
|
||||
file_picker: 3e6c3790de664ccf9b882732d9db5eaf6b8d4eb1
|
||||
connectivity: c4130b2985d4ef6fd26f9702e886bd5260681467
|
||||
Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
|
||||
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
|
||||
integration_test: 5ed24a436eb7ec17b6a13046e9bf7ca4a404e59e
|
||||
SDWebImage: b969dcfc02c40a5da71eac0b03b8f1a0c794a86f
|
||||
shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d
|
||||
SwiftyGif: e466e86c660d343357ab944a819a101c4127cb40
|
||||
url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
|
||||
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
||||
integration_test: 6eb66a19f7104200dcfdd62bc0077e1b09686e4f
|
||||
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
|
||||
Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
|
||||
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
|
||||
|
||||
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
|
||||
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:Runner.xcodeproj">
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 564 B After Width: | Height: | Size: 675 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 998 B |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 8.2 KiB |
@@ -1,61 +1,57 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/material.dart' show BoxFit, Center, SizedBox;
|
||||
|
||||
// ignore: uri_does_not_exist
|
||||
import 'cookie_client_stub.dart'
|
||||
// ignore: uri_does_not_exist
|
||||
if (dart.library.html) 'browser_cookie_client.dart'
|
||||
// ignore: uri_does_not_exist
|
||||
if (dart.library.io) 'io_cookie_client.dart';
|
||||
import 'package:imagini/api/cookie_client/cookie_client.dart'
|
||||
if (dart.library.html) 'package:imagini/api/cookie_client/browser_cookie_client.dart'
|
||||
if (dart.library.io) 'package:imagini/api/cookie_client/io_cookie_client.dart';
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:imagini/core/storage_client/base_storage_client.dart';
|
||||
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:graphql_flutter/graphql_flutter.dart';
|
||||
import 'package:imagini/graphql/imagini_graphql.dart';
|
||||
|
||||
class APIProvider{
|
||||
String _server, _accessToken, _refreshToken;
|
||||
|
||||
GraphQLClient _client;
|
||||
HttpLink httpLink;
|
||||
// CookieLink cookieLink;
|
||||
static const String _GRAPHQL_ENDPOINT = "/query";
|
||||
|
||||
APIProvider({
|
||||
@required String server,
|
||||
String accessToken,
|
||||
String refreshToken
|
||||
}) {
|
||||
_server = server;
|
||||
_accessToken = accessToken;
|
||||
_refreshToken = refreshToken;
|
||||
BaseStorageClient _storage;
|
||||
GraphQLClient _client;
|
||||
HttpLink httpLink;
|
||||
|
||||
APIProvider(BaseStorageClient storage) {
|
||||
_storage = storage;
|
||||
}
|
||||
|
||||
Future<void> init() async {
|
||||
String _server = await _storage.get("server");
|
||||
|
||||
// Initialize
|
||||
if (_server == null)
|
||||
_server = "http://localhost";
|
||||
|
||||
httpLink = HttpLink(_server + _GRAPHQL_ENDPOINT,
|
||||
httpClient: getCookieClient(),
|
||||
httpClient: getCookieClient(_storage),
|
||||
);
|
||||
|
||||
// cookieLink = CookieLink(_updateAccessToken, _updateRefreshToken);
|
||||
_client = GraphQLClient(
|
||||
cache: GraphQLCache(),
|
||||
link: httpLink,
|
||||
);
|
||||
}
|
||||
|
||||
// void _updateAccessToken(_accessToken) {
|
||||
// print("Updating Access Token: $_accessToken");
|
||||
// this._accessToken = _accessToken;
|
||||
// }
|
||||
|
||||
// void _updateRefreshToken(_refreshToken) {
|
||||
// print("Updating Refresh Token: $_accessToken");
|
||||
// this._refreshToken = _refreshToken;
|
||||
// }
|
||||
|
||||
Future<Login$Query$AuthResponse> login([
|
||||
Future<QueryResult> login(
|
||||
String username,
|
||||
String password,
|
||||
]) async {
|
||||
String server,
|
||||
) async {
|
||||
assert(
|
||||
(username != null && password != null)
|
||||
(username != null && password != null && server != null)
|
||||
);
|
||||
|
||||
// Initialize New Connection
|
||||
await _storage.set("server", server);
|
||||
await init();
|
||||
|
||||
QueryResult response = await _client.query(
|
||||
QueryOptions(
|
||||
document: LoginQuery().document,
|
||||
@@ -65,79 +61,53 @@ class APIProvider{
|
||||
},
|
||||
)
|
||||
);
|
||||
|
||||
final loginResponse = Login$Query.fromJson(response.data);
|
||||
return loginResponse.login;
|
||||
return response;
|
||||
}
|
||||
|
||||
Future<Me$Query$User> me() async {
|
||||
Future<CachedNetworkImage> getImage(String fileName, int width, int height) async {
|
||||
String server = await _storage.get("server");
|
||||
String accessToken = await _storage.get("accessToken");
|
||||
String refreshToken = await _storage.get("refreshToken");
|
||||
|
||||
String fullURL = "$server/media/$fileName?width=$width";
|
||||
print(fullURL);
|
||||
return CachedNetworkImage(
|
||||
imageUrl: fullURL,
|
||||
placeholder: (context, url) => Center(
|
||||
child: SizedBox(
|
||||
width: width.toDouble() / 3.5,
|
||||
height: height.toDouble() / 3.5,
|
||||
child: new PlatformCircularProgressIndicator(),
|
||||
),
|
||||
),
|
||||
imageRenderMethodForWeb: ImageRenderMethodForWeb.HttpGet,
|
||||
httpHeaders: {
|
||||
"X-Imagini-AccessToken": accessToken,
|
||||
"X-Imagini-RefreshToken": refreshToken,
|
||||
},
|
||||
fit: BoxFit.contain,
|
||||
);
|
||||
}
|
||||
|
||||
Future<QueryResult> me() async {
|
||||
QueryResult response = await _client.query(
|
||||
QueryOptions(
|
||||
document: MeQuery().document,
|
||||
)
|
||||
);
|
||||
|
||||
final meResponse = Me$Query.fromJson(response.data);
|
||||
return meResponse.me;
|
||||
return response;
|
||||
}
|
||||
|
||||
Future<String> mediaItems([
|
||||
String startDate,
|
||||
String endDate,
|
||||
String albumID,
|
||||
List<String> tagID,
|
||||
String type, // TODO: Make enum
|
||||
int page,
|
||||
]) async {
|
||||
// Query:
|
||||
// /api/v1/MediaItems
|
||||
// Derive Params:
|
||||
// startDate:
|
||||
// &createdAt=>2020-10-10T10:10:10
|
||||
// endDate:
|
||||
// &createdAt=<2020-10-10T10:10:10
|
||||
// albumID:
|
||||
// &albumID=9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d
|
||||
// tagID:
|
||||
// &tagID=9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d,9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d
|
||||
// type:
|
||||
// &type=Photos
|
||||
// &type=Videos
|
||||
// page:
|
||||
// &page=4
|
||||
|
||||
// Returns:
|
||||
// {
|
||||
//
|
||||
// }
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<String> tags([
|
||||
int page
|
||||
]) async {
|
||||
// Query:
|
||||
// /api/v1/Tags
|
||||
// Derive Params:
|
||||
// page:
|
||||
// &page=4
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<String> albums([
|
||||
int page
|
||||
]) async {
|
||||
// Query:
|
||||
// /api/v1/Albums
|
||||
// Derive Params:
|
||||
// page:
|
||||
// &page=4
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<String> me() async {
|
||||
return null;
|
||||
Future<QueryResult> mediaItems(Page page) async {
|
||||
QueryResult response = await _client.query(
|
||||
QueryOptions(
|
||||
document: MediaItemsQuery().document,
|
||||
variables: {
|
||||
"page": page,
|
||||
},
|
||||
)
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
void dispose() {}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
import 'package:http/browser_client.dart';
|
||||
import "package:http/http.dart";
|
||||
|
||||
BaseClient getCookieClient() => ClientWithCookies();
|
||||
|
||||
class ClientWithCookies extends BrowserClient {
|
||||
String _accessToken = "asdasdasd";
|
||||
String _refreshToken;
|
||||
|
||||
@override
|
||||
Future<StreamedResponse> send(BaseRequest request) async {
|
||||
request.headers.addAll({
|
||||
'X-Imagini-AccessToken': _accessToken,
|
||||
'X-Imagini-RefreshToken': _refreshToken,
|
||||
});
|
||||
|
||||
return super.send(request).then((response) {
|
||||
if (response.headers.containsKey("x-imagini-accesstoken")) {
|
||||
this._accessToken = response.headers["x-imagini-accesstoken"];
|
||||
}
|
||||
if (response.headers.containsKey("x-imagini-refreshtoken")) {
|
||||
this._refreshToken = response.headers["x-imagini-refreshtoken"];
|
||||
}
|
||||
|
||||
print("Access Token: $_accessToken");
|
||||
print("Refresh Token: $_refreshToken");
|
||||
return response;
|
||||
});
|
||||
}
|
||||
}
|
||||
36
web_native/lib/api/cookie_client/browser_cookie_client.dart
Normal file
@@ -0,0 +1,36 @@
|
||||
import 'package:http/browser_client.dart';
|
||||
import "package:http/http.dart";
|
||||
import "package:imagini/core/storage_client/base_storage_client.dart";
|
||||
|
||||
BaseClient getCookieClient(storage) => ClientWithCookies(storage);
|
||||
|
||||
class ClientWithCookies extends BrowserClient {
|
||||
BaseStorageClient _storage;
|
||||
|
||||
ClientWithCookies(BaseStorageClient storage) {
|
||||
_storage = storage;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<StreamedResponse> send(BaseRequest request) async {
|
||||
String _accessToken = await _storage.get("accessToken");
|
||||
String _refreshToken = await _storage.get("refreshToken");
|
||||
|
||||
request.headers.addAll({
|
||||
'X-Imagini-AccessToken': _accessToken,
|
||||
'X-Imagini-RefreshToken': _refreshToken,
|
||||
});
|
||||
|
||||
return super.send(request).then((response) async {
|
||||
// We've been told to update our access token
|
||||
if (response.headers.containsKey("x-imagini-accesstoken")) {
|
||||
await _storage.set("accessToken", response.headers["x-imagini-accesstoken"]);
|
||||
}
|
||||
// We've been told to update our refresh token
|
||||
if (response.headers.containsKey("x-imagini-refreshtoken")) {
|
||||
await _storage.set("refreshToken", response.headers["x-imagini-refreshtoken"]);
|
||||
}
|
||||
return response;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:http/http.dart';
|
||||
|
||||
BaseClient getCookieClient() => throw UnsupportedError(
|
||||
BaseClient getCookieClient(storage) => throw UnsupportedError(
|
||||
'Cannot create a client without dart:html or dart:io.');
|
||||
36
web_native/lib/api/cookie_client/io_cookie_client.dart
Normal file
@@ -0,0 +1,36 @@
|
||||
import 'package:http/io_client.dart';
|
||||
import "package:http/http.dart";
|
||||
import "package:imagini/core/storage_client/base_storage_client.dart";
|
||||
|
||||
BaseClient getCookieClient(storage) => IOClientWithCookies(storage);
|
||||
|
||||
class IOClientWithCookies extends IOClient {
|
||||
BaseStorageClient _storage;
|
||||
|
||||
IOClientWithCookies(BaseStorageClient storage) {
|
||||
_storage = storage;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<IOStreamedResponse> send(BaseRequest request) async {
|
||||
String _accessToken = await _storage.get("accessToken");
|
||||
String _refreshToken = await _storage.get("refreshToken");
|
||||
|
||||
request.headers.addAll({
|
||||
'X-Imagini-AccessToken': _accessToken,
|
||||
'X-Imagini-RefreshToken': _refreshToken,
|
||||
});
|
||||
|
||||
return super.send(request).then((response) async {
|
||||
// We've been told to update our access token
|
||||
if (response.headers.containsKey("x-imagini-accesstoken")) {
|
||||
await _storage.set("accessToken", response.headers["x-imagini-accesstoken"]);
|
||||
}
|
||||
// We've been told to update our refresh token
|
||||
if (response.headers.containsKey("x-imagini-refreshtoken")) {
|
||||
await _storage.set("refreshToken", response.headers["x-imagini-refreshtoken"]);
|
||||
}
|
||||
return response;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,45 @@
|
||||
import 'dart:async';
|
||||
import 'package:imagini/api/api_provider.dart';
|
||||
import 'package:imagini/graphql/imagini_graphql.dart';
|
||||
import 'package:graphql_flutter/graphql_flutter.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
|
||||
class ImaginiAPIRepository {
|
||||
APIProvider _apiProvider;
|
||||
|
||||
ImaginiAPIRepository(this._apiProvider);
|
||||
|
||||
Stream<Login$Query$AuthResponse> login(String user, password) {
|
||||
return Stream.fromFuture(_apiProvider.login(user, password));
|
||||
Stream<bool> login(String user, password, server) {
|
||||
return Stream.fromFuture(_apiProvider.login(user, password, server).then((QueryResult resp) {
|
||||
if (resp.exception != null)
|
||||
return false;
|
||||
|
||||
final loginResponse = Login$Query.fromJson(resp.data);
|
||||
if (loginResponse.login.result == AuthResult.failure)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
Stream<QueryResult> me() {
|
||||
return Stream.fromFuture(_apiProvider.me());
|
||||
}
|
||||
|
||||
Future<MediaItems$Query> mediaItems(Page page) async {
|
||||
QueryResult allItems = await _apiProvider.mediaItems(page);
|
||||
return MediaItems$Query.fromJson(allItems.data);
|
||||
}
|
||||
|
||||
Stream<bool> isAuthenticated() {
|
||||
return Stream.fromFuture(_apiProvider.me().then((QueryResult resp) {
|
||||
if (resp.exception != null)
|
||||
return false;
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
Future<CachedNetworkImage> getImage(String fileName, int width, int height) {
|
||||
return _apiProvider.getImage(fileName, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
import 'package:http/io_client.dart';
|
||||
import "package:http/http.dart";
|
||||
|
||||
BaseClient getCookieClient() => IOClientWithCookies();
|
||||
|
||||
class IOClientWithCookies extends IOClient {
|
||||
String _accessToken;
|
||||
String _refreshToken;
|
||||
|
||||
@override
|
||||
Future<IOStreamedResponse> send(BaseRequest request) async {
|
||||
// String cookie = await getCookie();
|
||||
// String getCookieString(String _) => cookie;
|
||||
// request.headers.update('cookie', getCookieString);
|
||||
return super.send(request).then((response) {
|
||||
if (response.headers.containsKey("x-imagini-accesstoken")) {
|
||||
this._accessToken = response.headers["x-imagini-accesstoken"];
|
||||
}
|
||||
if (response.headers.containsKey("x-imagini-refreshtoken")) {
|
||||
this._refreshToken = response.headers["x-imagini-refreshtoken"];
|
||||
}
|
||||
|
||||
print("Access Token: $_accessToken");
|
||||
print("Refresh Token: $_refreshToken");
|
||||
return response;
|
||||
});
|
||||
}
|
||||
}
|
||||
68
web_native/lib/blocs/home_bloc.dart
Normal file
@@ -0,0 +1,68 @@
|
||||
import 'dart:async';
|
||||
import 'package:imagini/core/imagini_application.dart';
|
||||
import 'package:imagini/api/imagini_api_repository.dart';
|
||||
import 'package:imagini/graphql/imagini_graphql.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
|
||||
class HomeBloc{
|
||||
|
||||
final ImaginiApplication _application;
|
||||
ImaginiAPIRepository _imaginiAPI;
|
||||
|
||||
final _loginController = StreamController<bool>.broadcast();
|
||||
Stream<bool> get loginResult => _loginController.stream;
|
||||
|
||||
final _authenticatedController = StreamController<bool>.broadcast();
|
||||
Stream<bool> get authenticatedResult => _authenticatedController.stream;
|
||||
|
||||
Map<int, List<MediaItems$Query$MediaItemResponse$MediaItem>> _pagedMediaItemListCache =
|
||||
Map<int, List<MediaItems$Query$MediaItemResponse$MediaItem>>();
|
||||
|
||||
int totalMediaItems;
|
||||
int _pageSize = 50;
|
||||
|
||||
HomeBloc(this._application){
|
||||
_init();
|
||||
}
|
||||
|
||||
void _init(){
|
||||
_imaginiAPI = _application.imaginiAPI;
|
||||
}
|
||||
|
||||
void dispose(){
|
||||
_loginController.close();
|
||||
_authenticatedController.close();
|
||||
}
|
||||
|
||||
Future<CachedNetworkImage> getMedia(int index, derivedContentWidth) async {
|
||||
MediaItems$Query$MediaItemResponse$MediaItem mediaDetails = await getMediaDetails(index);
|
||||
if (mediaDetails == null)
|
||||
return null;
|
||||
int derivedContentHeight = (mediaDetails.height / mediaDetails.width * derivedContentWidth).ceil();
|
||||
return _imaginiAPI.getImage(mediaDetails.fileName, derivedContentWidth, derivedContentHeight);
|
||||
}
|
||||
|
||||
Future<MediaItems$Query$MediaItemResponse$MediaItem> getMediaDetails(int index) async {
|
||||
int itemPage = (index / _pageSize).ceil();
|
||||
int indexOnPage = index % _pageSize;
|
||||
|
||||
if (!_pagedMediaItemListCache.containsKey(itemPage))
|
||||
await _cachePage(itemPage);
|
||||
|
||||
return _pagedMediaItemListCache[itemPage][indexOnPage];
|
||||
}
|
||||
|
||||
_cachePage(int itemPage) async {
|
||||
MediaItems$Query newItems = await _imaginiAPI.mediaItems(Page(page: itemPage));
|
||||
totalMediaItems = newItems.mediaItems.page.total;
|
||||
_pagedMediaItemListCache[itemPage] = newItems.mediaItems.data;
|
||||
}
|
||||
|
||||
checkAuthentication(){
|
||||
_authenticatedController.addStream(_imaginiAPI.isAuthenticated());
|
||||
}
|
||||
|
||||
attemptHome(String username, password, server){
|
||||
_loginController.addStream(_imaginiAPI.login(username, password, server));
|
||||
}
|
||||
}
|
||||
40
web_native/lib/blocs/login_bloc.dart
Normal file
@@ -0,0 +1,40 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:imagini/core/imagini_application.dart';
|
||||
import 'package:imagini/api/imagini_api_repository.dart';
|
||||
|
||||
class LoginBloc{
|
||||
|
||||
final ImaginiApplication _application;
|
||||
ImaginiAPIRepository _imaginiAPI;
|
||||
|
||||
final _loginController = StreamController<bool>.broadcast();
|
||||
Stream<bool> get loginResult => _loginController.stream;
|
||||
|
||||
final _authenticatedController = StreamController<bool>.broadcast();
|
||||
Stream<bool> get authenticatedResult => _authenticatedController.stream;
|
||||
|
||||
LoginBloc(this._application){
|
||||
_init();
|
||||
}
|
||||
|
||||
void _init(){
|
||||
_imaginiAPI = _application.imaginiAPI;
|
||||
checkAuthentication();
|
||||
|
||||
// attemptLogin("admin", "admin", "http://localhost:8484");
|
||||
}
|
||||
|
||||
void dispose(){
|
||||
_loginController.close();
|
||||
_authenticatedController.close();
|
||||
}
|
||||
|
||||
checkAuthentication(){
|
||||
_authenticatedController.addStream(_imaginiAPI.isAuthenticated());
|
||||
}
|
||||
|
||||
attemptLogin(String username, password, server){
|
||||
_loginController.addStream(_imaginiAPI.login(username, password, server));
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:imagini/core/imagini_application.dart';
|
||||
import 'package:imagini/api/imagini_api_repository.dart';
|
||||
import 'package:imagini/graphql/imagini_graphql.dart';
|
||||
|
||||
class SplashBloc{
|
||||
|
||||
final ImaginiApplication _application;
|
||||
|
||||
final _loginController = StreamController<Login$Query$AuthResponse>();
|
||||
Stream<Login$Query$AuthResponse> get loginResult => _loginController.stream;
|
||||
|
||||
SplashBloc(this._application){
|
||||
_init();
|
||||
}
|
||||
|
||||
void _init(){
|
||||
// Do Initial Load
|
||||
initializeLogin();
|
||||
}
|
||||
|
||||
void dispose(){
|
||||
_loginController.close();
|
||||
}
|
||||
|
||||
initializeLogin(){
|
||||
ImaginiAPIRepository imaginiAPI = _application.imaginiAPI;
|
||||
|
||||
// TODO: This should actually attempt to load the existing Tokens, not login
|
||||
_loginController.addStream(imaginiAPI.login("admin", "admin"));
|
||||
|
||||
// imaginiAPI.login("admin", "admin1").listen((LoginResponse lr) {
|
||||
// });
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,6 @@ class AppComponentState extends State<AppComponent> {
|
||||
|
||||
@override
|
||||
void dispose() async {
|
||||
// Log.info('dispose');
|
||||
super.dispose();
|
||||
await _application.onTerminate();
|
||||
}
|
||||
|
||||
@@ -3,13 +3,13 @@ import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:imagini/screens/home_screen.dart';
|
||||
import 'package:imagini/screens/login_screen.dart';
|
||||
import 'package:imagini/screens/splash_screen.dart';
|
||||
// import 'package:imagini/screens/splash_screen.dart';
|
||||
|
||||
var splashHandler = new Handler(
|
||||
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
|
||||
return SplashScreen();
|
||||
}
|
||||
);
|
||||
// var splashHandler = new Handler(
|
||||
// handlerFunc: (BuildContext context, Map<String, List<String>> params) {
|
||||
// return SplashScreen();
|
||||
// }
|
||||
// );
|
||||
|
||||
var loginHandler = new Handler(
|
||||
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
|
||||
@@ -42,7 +42,7 @@ class AppRoutes {
|
||||
return;
|
||||
}
|
||||
);
|
||||
router.define(SplashScreen.PATH, handler: splashHandler);
|
||||
// router.define(SplashScreen.PATH, handler: splashHandler);
|
||||
router.define(LoginScreen.PATH, handler: loginHandler);
|
||||
router.define(HomeScreen.PATH, handler: homeHandler);
|
||||
// router.define(AppDetailPage.PATH, handler: appDetailRouteHandler);
|
||||
|
||||
@@ -3,14 +3,21 @@ import 'package:fluro/fluro.dart';
|
||||
import 'package:imagini/core/app_routes.dart';
|
||||
import 'package:imagini/api/api_provider.dart';
|
||||
import 'package:imagini/api/imagini_api_repository.dart';
|
||||
import 'package:imagini/core/storage_client/base_storage_client.dart';
|
||||
|
||||
import 'package:imagini/core/storage_client/storage_client.dart'
|
||||
if (dart.library.html) 'package:imagini/core/storage_client/browser_storage_client.dart'
|
||||
if (dart.library.io) 'package:imagini/core/storage_client/mobile_storage_client.dart';
|
||||
|
||||
class ImaginiApplication {
|
||||
FluroRouter router;
|
||||
ImaginiAPIRepository imaginiAPI;
|
||||
BaseStorageClient storageClient;
|
||||
|
||||
Future<void> onCreate() async {
|
||||
_initRouter();
|
||||
_initAPIRepository();
|
||||
_initStorageClient();
|
||||
await _initAPIRepository();
|
||||
}
|
||||
|
||||
Future<void> onTerminate() async {}
|
||||
@@ -20,8 +27,14 @@ class ImaginiApplication {
|
||||
AppRoutes.configureRoutes(router);
|
||||
}
|
||||
|
||||
_initAPIRepository() {
|
||||
APIProvider apiProvider = new APIProvider(server: "http://localhost:8484");
|
||||
_initStorageClient() {
|
||||
storageClient = getStorageClient();
|
||||
}
|
||||
|
||||
_initAPIRepository() async {
|
||||
// TODO: Get from config
|
||||
APIProvider apiProvider = new APIProvider(storageClient);
|
||||
await apiProvider.init();
|
||||
imaginiAPI = ImaginiAPIRepository(apiProvider);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
abstract class BaseStorageClient {
|
||||
Future<String> get(String key);
|
||||
Future<void> set(String key, String value);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import 'dart:html';
|
||||
|
||||
import './base_storage_client.dart';
|
||||
|
||||
BaseStorageClient getStorageClient() => BrowserStorageClient();
|
||||
|
||||
class BrowserStorageClient extends BaseStorageClient {
|
||||
@override
|
||||
Future<String> get(String key) async {
|
||||
var requestedValue = window.localStorage.containsKey(key) ? window.localStorage[key] : "";
|
||||
return requestedValue;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> set(String key, String value) async {
|
||||
window.localStorage[key] = value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
|
||||
import './base_storage_client.dart';
|
||||
|
||||
BaseStorageClient getStorageClient() => MobileStorageClient();
|
||||
|
||||
class MobileStorageClient extends BaseStorageClient {
|
||||
final storage = new FlutterSecureStorage();
|
||||
|
||||
@override
|
||||
Future<String> get(String key) async {
|
||||
return storage.read(key: key);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> set(String key, String value) async {
|
||||
return storage.write(key: key, value: value);
|
||||
}
|
||||
}
|
||||
4
web_native/lib/core/storage_client/storage_client.dart
Normal file
@@ -0,0 +1,4 @@
|
||||
import './base_storage_client.dart';
|
||||
|
||||
BaseStorageClient getStorageClient() => throw UnsupportedError(
|
||||
'Cannot create a storage client.');
|
||||
@@ -9,6 +9,62 @@ import 'package:http/http.dart';
|
||||
import 'package:imagini/helpers/upload_serializer.dart';
|
||||
part 'imagini_graphql.graphql.g.dart';
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class Me$Query$User with EquatableMixin {
|
||||
Me$Query$User();
|
||||
|
||||
factory Me$Query$User.fromJson(Map<String, dynamic> json) =>
|
||||
_$Me$Query$UserFromJson(json);
|
||||
|
||||
String id;
|
||||
|
||||
DateTime createdAt;
|
||||
|
||||
DateTime updatedAt;
|
||||
|
||||
String email;
|
||||
|
||||
String username;
|
||||
|
||||
String firstName;
|
||||
|
||||
String lastName;
|
||||
|
||||
@JsonKey(unknownEnumValue: Role.artemisUnknown)
|
||||
Role role;
|
||||
|
||||
@JsonKey(unknownEnumValue: AuthType.artemisUnknown)
|
||||
AuthType authType;
|
||||
|
||||
@override
|
||||
List<Object> get props => [
|
||||
id,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
email,
|
||||
username,
|
||||
firstName,
|
||||
lastName,
|
||||
role,
|
||||
authType
|
||||
];
|
||||
Map<String, dynamic> toJson() => _$Me$Query$UserToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class Me$Query with EquatableMixin {
|
||||
Me$Query();
|
||||
|
||||
factory Me$Query.fromJson(Map<String, dynamic> json) =>
|
||||
_$Me$QueryFromJson(json);
|
||||
|
||||
Me$Query$User me;
|
||||
|
||||
@override
|
||||
List<Object> get props => [me];
|
||||
Map<String, dynamic> toJson() => _$Me$QueryToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class Login$Query$AuthResponse$Device with EquatableMixin {
|
||||
Login$Query$AuthResponse$Device();
|
||||
@@ -115,69 +171,374 @@ class CreateMediaItem$Mutation with EquatableMixin {
|
||||
}
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class Me$Query$User with EquatableMixin {
|
||||
Me$Query$User();
|
||||
class MediaItems$Query$MediaItemResponse$MediaItem with EquatableMixin {
|
||||
MediaItems$Query$MediaItemResponse$MediaItem();
|
||||
|
||||
factory Me$Query$User.fromJson(Map<String, dynamic> json) =>
|
||||
_$Me$Query$UserFromJson(json);
|
||||
factory MediaItems$Query$MediaItemResponse$MediaItem.fromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
_$MediaItems$Query$MediaItemResponse$MediaItemFromJson(json);
|
||||
|
||||
String id;
|
||||
|
||||
String fileName;
|
||||
|
||||
double latitude;
|
||||
|
||||
double longitude;
|
||||
|
||||
bool isVideo;
|
||||
|
||||
int width;
|
||||
|
||||
int height;
|
||||
|
||||
String origName;
|
||||
|
||||
DateTime createdAt;
|
||||
|
||||
DateTime updatedAt;
|
||||
@override
|
||||
List<Object> get props => [
|
||||
id,
|
||||
fileName,
|
||||
latitude,
|
||||
longitude,
|
||||
isVideo,
|
||||
width,
|
||||
height,
|
||||
origName,
|
||||
createdAt
|
||||
];
|
||||
Map<String, dynamic> toJson() =>
|
||||
_$MediaItems$Query$MediaItemResponse$MediaItemToJson(this);
|
||||
}
|
||||
|
||||
String email;
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class MediaItems$Query$MediaItemResponse$PageResponse with EquatableMixin {
|
||||
MediaItems$Query$MediaItemResponse$PageResponse();
|
||||
|
||||
String username;
|
||||
factory MediaItems$Query$MediaItemResponse$PageResponse.fromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
_$MediaItems$Query$MediaItemResponse$PageResponseFromJson(json);
|
||||
|
||||
String firstName;
|
||||
int size;
|
||||
|
||||
String lastName;
|
||||
int page;
|
||||
|
||||
@JsonKey(unknownEnumValue: Role.artemisUnknown)
|
||||
Role role;
|
||||
int total;
|
||||
|
||||
@JsonKey(unknownEnumValue: AuthType.artemisUnknown)
|
||||
AuthType authType;
|
||||
@override
|
||||
List<Object> get props => [size, page, total];
|
||||
Map<String, dynamic> toJson() =>
|
||||
_$MediaItems$Query$MediaItemResponse$PageResponseToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class MediaItems$Query$MediaItemResponse with EquatableMixin {
|
||||
MediaItems$Query$MediaItemResponse();
|
||||
|
||||
factory MediaItems$Query$MediaItemResponse.fromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
_$MediaItems$Query$MediaItemResponseFromJson(json);
|
||||
|
||||
List<MediaItems$Query$MediaItemResponse$MediaItem> data;
|
||||
|
||||
MediaItems$Query$MediaItemResponse$PageResponse page;
|
||||
|
||||
@override
|
||||
List<Object> get props => [data, page];
|
||||
Map<String, dynamic> toJson() =>
|
||||
_$MediaItems$Query$MediaItemResponseToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class MediaItems$Query with EquatableMixin {
|
||||
MediaItems$Query();
|
||||
|
||||
factory MediaItems$Query.fromJson(Map<String, dynamic> json) =>
|
||||
_$MediaItems$QueryFromJson(json);
|
||||
|
||||
MediaItems$Query$MediaItemResponse mediaItems;
|
||||
|
||||
@override
|
||||
List<Object> get props => [mediaItems];
|
||||
Map<String, dynamic> toJson() => _$MediaItems$QueryToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class TimeFilter with EquatableMixin {
|
||||
TimeFilter(
|
||||
{this.equalTo,
|
||||
this.notEqualTo,
|
||||
this.lessThan,
|
||||
this.lessThanOrEqualTo,
|
||||
this.greaterThan,
|
||||
this.greaterThanOrEqualTo});
|
||||
|
||||
factory TimeFilter.fromJson(Map<String, dynamic> json) =>
|
||||
_$TimeFilterFromJson(json);
|
||||
|
||||
DateTime equalTo;
|
||||
|
||||
DateTime notEqualTo;
|
||||
|
||||
DateTime lessThan;
|
||||
|
||||
DateTime lessThanOrEqualTo;
|
||||
|
||||
DateTime greaterThan;
|
||||
|
||||
DateTime greaterThanOrEqualTo;
|
||||
|
||||
@override
|
||||
List<Object> get props => [
|
||||
equalTo,
|
||||
notEqualTo,
|
||||
lessThan,
|
||||
lessThanOrEqualTo,
|
||||
greaterThan,
|
||||
greaterThanOrEqualTo
|
||||
];
|
||||
Map<String, dynamic> toJson() => _$TimeFilterToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class FloatFilter with EquatableMixin {
|
||||
FloatFilter(
|
||||
{this.equalTo,
|
||||
this.notEqualTo,
|
||||
this.lessThan,
|
||||
this.lessThanOrEqualTo,
|
||||
this.greaterThan,
|
||||
this.greaterThanOrEqualTo});
|
||||
|
||||
factory FloatFilter.fromJson(Map<String, dynamic> json) =>
|
||||
_$FloatFilterFromJson(json);
|
||||
|
||||
double equalTo;
|
||||
|
||||
double notEqualTo;
|
||||
|
||||
double lessThan;
|
||||
|
||||
double lessThanOrEqualTo;
|
||||
|
||||
double greaterThan;
|
||||
|
||||
double greaterThanOrEqualTo;
|
||||
|
||||
@override
|
||||
List<Object> get props => [
|
||||
equalTo,
|
||||
notEqualTo,
|
||||
lessThan,
|
||||
lessThanOrEqualTo,
|
||||
greaterThan,
|
||||
greaterThanOrEqualTo
|
||||
];
|
||||
Map<String, dynamic> toJson() => _$FloatFilterToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class BooleanFilter with EquatableMixin {
|
||||
BooleanFilter({this.equalTo, this.notEqualTo});
|
||||
|
||||
factory BooleanFilter.fromJson(Map<String, dynamic> json) =>
|
||||
_$BooleanFilterFromJson(json);
|
||||
|
||||
bool equalTo;
|
||||
|
||||
bool notEqualTo;
|
||||
|
||||
@override
|
||||
List<Object> get props => [equalTo, notEqualTo];
|
||||
Map<String, dynamic> toJson() => _$BooleanFilterToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class IDFilter with EquatableMixin {
|
||||
IDFilter({this.equalTo, this.notEqualTo});
|
||||
|
||||
factory IDFilter.fromJson(Map<String, dynamic> json) =>
|
||||
_$IDFilterFromJson(json);
|
||||
|
||||
String equalTo;
|
||||
|
||||
String notEqualTo;
|
||||
|
||||
@override
|
||||
List<Object> get props => [equalTo, notEqualTo];
|
||||
Map<String, dynamic> toJson() => _$IDFilterToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class StringFilter with EquatableMixin {
|
||||
StringFilter(
|
||||
{this.equalTo,
|
||||
this.notEqualTo,
|
||||
this.startsWith,
|
||||
this.notStartsWith,
|
||||
this.endsWith,
|
||||
this.notEndsWith,
|
||||
this.contains,
|
||||
this.notContains});
|
||||
|
||||
factory StringFilter.fromJson(Map<String, dynamic> json) =>
|
||||
_$StringFilterFromJson(json);
|
||||
|
||||
String equalTo;
|
||||
|
||||
String notEqualTo;
|
||||
|
||||
String startsWith;
|
||||
|
||||
String notStartsWith;
|
||||
|
||||
String endsWith;
|
||||
|
||||
String notEndsWith;
|
||||
|
||||
String contains;
|
||||
|
||||
String notContains;
|
||||
|
||||
@override
|
||||
List<Object> get props => [
|
||||
equalTo,
|
||||
notEqualTo,
|
||||
startsWith,
|
||||
notStartsWith,
|
||||
endsWith,
|
||||
notEndsWith,
|
||||
contains,
|
||||
notContains
|
||||
];
|
||||
Map<String, dynamic> toJson() => _$StringFilterToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class MediaItemFilter with EquatableMixin {
|
||||
MediaItemFilter(
|
||||
{this.id,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.exifDate,
|
||||
this.latitude,
|
||||
this.longitude,
|
||||
this.isVideo,
|
||||
this.origName,
|
||||
this.tags,
|
||||
this.albums});
|
||||
|
||||
factory MediaItemFilter.fromJson(Map<String, dynamic> json) =>
|
||||
_$MediaItemFilterFromJson(json);
|
||||
|
||||
IDFilter id;
|
||||
|
||||
TimeFilter createdAt;
|
||||
|
||||
TimeFilter updatedAt;
|
||||
|
||||
TimeFilter exifDate;
|
||||
|
||||
FloatFilter latitude;
|
||||
|
||||
FloatFilter longitude;
|
||||
|
||||
BooleanFilter isVideo;
|
||||
|
||||
StringFilter origName;
|
||||
|
||||
TagFilter tags;
|
||||
|
||||
AlbumFilter albums;
|
||||
|
||||
@override
|
||||
List<Object> get props => [
|
||||
id,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
email,
|
||||
username,
|
||||
firstName,
|
||||
lastName,
|
||||
role,
|
||||
authType
|
||||
exifDate,
|
||||
latitude,
|
||||
longitude,
|
||||
isVideo,
|
||||
origName,
|
||||
tags,
|
||||
albums
|
||||
];
|
||||
Map<String, dynamic> toJson() => _$Me$Query$UserToJson(this);
|
||||
Map<String, dynamic> toJson() => _$MediaItemFilterToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class Me$Query with EquatableMixin {
|
||||
Me$Query();
|
||||
class TagFilter with EquatableMixin {
|
||||
TagFilter({this.id, this.createdAt, this.updatedAt, this.name});
|
||||
|
||||
factory Me$Query.fromJson(Map<String, dynamic> json) =>
|
||||
_$Me$QueryFromJson(json);
|
||||
factory TagFilter.fromJson(Map<String, dynamic> json) =>
|
||||
_$TagFilterFromJson(json);
|
||||
|
||||
Me$Query$User me;
|
||||
IDFilter id;
|
||||
|
||||
TimeFilter createdAt;
|
||||
|
||||
TimeFilter updatedAt;
|
||||
|
||||
StringFilter name;
|
||||
|
||||
@override
|
||||
List<Object> get props => [me];
|
||||
Map<String, dynamic> toJson() => _$Me$QueryToJson(this);
|
||||
List<Object> get props => [id, createdAt, updatedAt, name];
|
||||
Map<String, dynamic> toJson() => _$TagFilterToJson(this);
|
||||
}
|
||||
|
||||
enum AuthResult {
|
||||
@JsonValue('Success')
|
||||
success,
|
||||
@JsonValue('Failure')
|
||||
failure,
|
||||
@JsonValue('ARTEMIS_UNKNOWN')
|
||||
artemisUnknown,
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class AlbumFilter with EquatableMixin {
|
||||
AlbumFilter({this.id, this.createdAt, this.updatedAt, this.name});
|
||||
|
||||
factory AlbumFilter.fromJson(Map<String, dynamic> json) =>
|
||||
_$AlbumFilterFromJson(json);
|
||||
|
||||
IDFilter id;
|
||||
|
||||
TimeFilter createdAt;
|
||||
|
||||
TimeFilter updatedAt;
|
||||
|
||||
StringFilter name;
|
||||
|
||||
@override
|
||||
List<Object> get props => [id, createdAt, updatedAt, name];
|
||||
Map<String, dynamic> toJson() => _$AlbumFilterToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class Page with EquatableMixin {
|
||||
Page({this.size, this.page});
|
||||
|
||||
factory Page.fromJson(Map<String, dynamic> json) => _$PageFromJson(json);
|
||||
|
||||
int size;
|
||||
|
||||
int page;
|
||||
|
||||
@override
|
||||
List<Object> get props => [size, page];
|
||||
Map<String, dynamic> toJson() => _$PageToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class Order with EquatableMixin {
|
||||
Order({this.by, this.direction});
|
||||
|
||||
factory Order.fromJson(Map<String, dynamic> json) => _$OrderFromJson(json);
|
||||
|
||||
String by;
|
||||
|
||||
@JsonKey(unknownEnumValue: OrderDirection.artemisUnknown)
|
||||
OrderDirection direction;
|
||||
|
||||
@override
|
||||
List<Object> get props => [by, direction];
|
||||
Map<String, dynamic> toJson() => _$OrderToJson(this);
|
||||
}
|
||||
|
||||
enum Role {
|
||||
@JsonValue('Admin')
|
||||
admin,
|
||||
@@ -194,6 +555,106 @@ enum AuthType {
|
||||
@JsonValue('ARTEMIS_UNKNOWN')
|
||||
artemisUnknown,
|
||||
}
|
||||
enum AuthResult {
|
||||
@JsonValue('Success')
|
||||
success,
|
||||
@JsonValue('Failure')
|
||||
failure,
|
||||
@JsonValue('ARTEMIS_UNKNOWN')
|
||||
artemisUnknown,
|
||||
}
|
||||
enum OrderDirection {
|
||||
@JsonValue('ASC')
|
||||
asc,
|
||||
@JsonValue('DESC')
|
||||
desc,
|
||||
@JsonValue('ARTEMIS_UNKNOWN')
|
||||
artemisUnknown,
|
||||
}
|
||||
|
||||
class MeQuery extends GraphQLQuery<Me$Query, JsonSerializable> {
|
||||
MeQuery();
|
||||
|
||||
@override
|
||||
final DocumentNode document = DocumentNode(definitions: [
|
||||
OperationDefinitionNode(
|
||||
type: OperationType.query,
|
||||
name: NameNode(value: 'me'),
|
||||
variableDefinitions: [],
|
||||
directives: [],
|
||||
selectionSet: SelectionSetNode(selections: [
|
||||
FieldNode(
|
||||
name: NameNode(value: 'me'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: SelectionSetNode(selections: [
|
||||
FieldNode(
|
||||
name: NameNode(value: 'id'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'createdAt'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'updatedAt'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'email'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'username'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'firstName'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'lastName'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'role'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'authType'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null)
|
||||
]))
|
||||
]))
|
||||
]);
|
||||
|
||||
@override
|
||||
final String operationName = 'me';
|
||||
|
||||
@override
|
||||
List<Object> get props => [document, operationName];
|
||||
@override
|
||||
Me$Query parse(Map<String, dynamic> json) => Me$Query.fromJson(json);
|
||||
}
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class LoginArguments extends JsonSerializable with EquatableMixin {
|
||||
@@ -425,19 +886,75 @@ class CreateMediaItemMutation
|
||||
CreateMediaItem$Mutation.fromJson(json);
|
||||
}
|
||||
|
||||
class MeQuery extends GraphQLQuery<Me$Query, JsonSerializable> {
|
||||
MeQuery();
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class MediaItemsArguments extends JsonSerializable with EquatableMixin {
|
||||
MediaItemsArguments({this.order, this.page, this.filter});
|
||||
|
||||
@override
|
||||
factory MediaItemsArguments.fromJson(Map<String, dynamic> json) =>
|
||||
_$MediaItemsArgumentsFromJson(json);
|
||||
|
||||
final Order order;
|
||||
|
||||
final Page page;
|
||||
|
||||
final MediaItemFilter filter;
|
||||
|
||||
@override
|
||||
List<Object> get props => [order, page, filter];
|
||||
@override
|
||||
Map<String, dynamic> toJson() => _$MediaItemsArgumentsToJson(this);
|
||||
}
|
||||
|
||||
class MediaItemsQuery
|
||||
extends GraphQLQuery<MediaItems$Query, MediaItemsArguments> {
|
||||
MediaItemsQuery({this.variables});
|
||||
|
||||
@override
|
||||
final DocumentNode document = DocumentNode(definitions: [
|
||||
OperationDefinitionNode(
|
||||
type: OperationType.query,
|
||||
name: NameNode(value: 'me'),
|
||||
variableDefinitions: [],
|
||||
name: NameNode(value: 'mediaItems'),
|
||||
variableDefinitions: [
|
||||
VariableDefinitionNode(
|
||||
variable: VariableNode(name: NameNode(value: 'order')),
|
||||
type: NamedTypeNode(
|
||||
name: NameNode(value: 'Order'), isNonNull: false),
|
||||
defaultValue: DefaultValueNode(value: null),
|
||||
directives: []),
|
||||
VariableDefinitionNode(
|
||||
variable: VariableNode(name: NameNode(value: 'page')),
|
||||
type: NamedTypeNode(
|
||||
name: NameNode(value: 'Page'), isNonNull: false),
|
||||
defaultValue: DefaultValueNode(value: null),
|
||||
directives: []),
|
||||
VariableDefinitionNode(
|
||||
variable: VariableNode(name: NameNode(value: 'filter')),
|
||||
type: NamedTypeNode(
|
||||
name: NameNode(value: 'MediaItemFilter'), isNonNull: false),
|
||||
defaultValue: DefaultValueNode(value: null),
|
||||
directives: [])
|
||||
],
|
||||
directives: [],
|
||||
selectionSet: SelectionSetNode(selections: [
|
||||
FieldNode(
|
||||
name: NameNode(value: 'me'),
|
||||
name: NameNode(value: 'mediaItems'),
|
||||
alias: null,
|
||||
arguments: [
|
||||
ArgumentNode(
|
||||
name: NameNode(value: 'filter'),
|
||||
value: VariableNode(name: NameNode(value: 'filter'))),
|
||||
ArgumentNode(
|
||||
name: NameNode(value: 'page'),
|
||||
value: VariableNode(name: NameNode(value: 'page'))),
|
||||
ArgumentNode(
|
||||
name: NameNode(value: 'order'),
|
||||
value: VariableNode(name: NameNode(value: 'order')))
|
||||
],
|
||||
directives: [],
|
||||
selectionSet: SelectionSetNode(selections: [
|
||||
FieldNode(
|
||||
name: NameNode(value: 'data'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
@@ -448,63 +965,93 @@ class MeQuery extends GraphQLQuery<Me$Query, JsonSerializable> {
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'fileName'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'latitude'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'longitude'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'isVideo'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'width'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'height'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'origName'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'createdAt'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
selectionSet: null)
|
||||
])),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'updatedAt'),
|
||||
name: NameNode(value: 'page'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: SelectionSetNode(selections: [
|
||||
FieldNode(
|
||||
name: NameNode(value: 'size'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'email'),
|
||||
name: NameNode(value: 'page'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'username'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'firstName'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'lastName'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'role'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'authType'),
|
||||
name: NameNode(value: 'total'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null)
|
||||
]))
|
||||
]))
|
||||
]))
|
||||
]);
|
||||
|
||||
@override
|
||||
final String operationName = 'me';
|
||||
final String operationName = 'mediaItems';
|
||||
|
||||
@override
|
||||
List<Object> get props => [document, operationName];
|
||||
final MediaItemsArguments variables;
|
||||
|
||||
@override
|
||||
Me$Query parse(Map<String, dynamic> json) => Me$Query.fromJson(json);
|
||||
List<Object> get props => [document, operationName, variables];
|
||||
@override
|
||||
MediaItems$Query parse(Map<String, dynamic> json) =>
|
||||
MediaItems$Query.fromJson(json);
|
||||
}
|
||||
|
||||
@@ -6,33 +6,36 @@ part of 'imagini_graphql.graphql.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Login$Query$AuthResponse$Device _$Login$Query$AuthResponse$DeviceFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return Login$Query$AuthResponse$Device()..id = json['id'] as String;
|
||||
Me$Query$User _$Me$Query$UserFromJson(Map<String, dynamic> json) {
|
||||
return Me$Query$User()
|
||||
..id = json['id'] as String
|
||||
..createdAt = json['createdAt'] == null
|
||||
? null
|
||||
: DateTime.parse(json['createdAt'] as String)
|
||||
..updatedAt = json['updatedAt'] == null
|
||||
? null
|
||||
: DateTime.parse(json['updatedAt'] as String)
|
||||
..email = json['email'] as String
|
||||
..username = json['username'] as String
|
||||
..firstName = json['firstName'] as String
|
||||
..lastName = json['lastName'] as String
|
||||
..role = _$enumDecodeNullable(_$RoleEnumMap, json['role'],
|
||||
unknownValue: Role.artemisUnknown)
|
||||
..authType = _$enumDecodeNullable(_$AuthTypeEnumMap, json['authType'],
|
||||
unknownValue: AuthType.artemisUnknown);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$Login$Query$AuthResponse$DeviceToJson(
|
||||
Login$Query$AuthResponse$Device instance) =>
|
||||
Map<String, dynamic> _$Me$Query$UserToJson(Me$Query$User instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
};
|
||||
|
||||
Login$Query$AuthResponse _$Login$Query$AuthResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return Login$Query$AuthResponse()
|
||||
..result = _$enumDecodeNullable(_$AuthResultEnumMap, json['result'],
|
||||
unknownValue: AuthResult.artemisUnknown)
|
||||
..device = json['device'] == null
|
||||
? null
|
||||
: Login$Query$AuthResponse$Device.fromJson(
|
||||
json['device'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$Login$Query$AuthResponseToJson(
|
||||
Login$Query$AuthResponse instance) =>
|
||||
<String, dynamic>{
|
||||
'result': _$AuthResultEnumMap[instance.result],
|
||||
'device': instance.device?.toJson(),
|
||||
'createdAt': instance.createdAt?.toIso8601String(),
|
||||
'updatedAt': instance.updatedAt?.toIso8601String(),
|
||||
'email': instance.email,
|
||||
'username': instance.username,
|
||||
'firstName': instance.firstName,
|
||||
'lastName': instance.lastName,
|
||||
'role': _$RoleEnumMap[instance.role],
|
||||
'authType': _$AuthTypeEnumMap[instance.authType],
|
||||
};
|
||||
|
||||
T _$enumDecode<T>(
|
||||
@@ -67,6 +70,58 @@ T _$enumDecodeNullable<T>(
|
||||
return _$enumDecode<T>(enumValues, source, unknownValue: unknownValue);
|
||||
}
|
||||
|
||||
const _$RoleEnumMap = {
|
||||
Role.admin: 'Admin',
|
||||
Role.user: 'User',
|
||||
Role.artemisUnknown: 'ARTEMIS_UNKNOWN',
|
||||
};
|
||||
|
||||
const _$AuthTypeEnumMap = {
|
||||
AuthType.local: 'Local',
|
||||
AuthType.ldap: 'LDAP',
|
||||
AuthType.artemisUnknown: 'ARTEMIS_UNKNOWN',
|
||||
};
|
||||
|
||||
Me$Query _$Me$QueryFromJson(Map<String, dynamic> json) {
|
||||
return Me$Query()
|
||||
..me = json['me'] == null
|
||||
? null
|
||||
: Me$Query$User.fromJson(json['me'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$Me$QueryToJson(Me$Query instance) => <String, dynamic>{
|
||||
'me': instance.me?.toJson(),
|
||||
};
|
||||
|
||||
Login$Query$AuthResponse$Device _$Login$Query$AuthResponse$DeviceFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return Login$Query$AuthResponse$Device()..id = json['id'] as String;
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$Login$Query$AuthResponse$DeviceToJson(
|
||||
Login$Query$AuthResponse$Device instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
};
|
||||
|
||||
Login$Query$AuthResponse _$Login$Query$AuthResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return Login$Query$AuthResponse()
|
||||
..result = _$enumDecodeNullable(_$AuthResultEnumMap, json['result'],
|
||||
unknownValue: AuthResult.artemisUnknown)
|
||||
..device = json['device'] == null
|
||||
? null
|
||||
: Login$Query$AuthResponse$Device.fromJson(
|
||||
json['device'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$Login$Query$AuthResponseToJson(
|
||||
Login$Query$AuthResponse instance) =>
|
||||
<String, dynamic>{
|
||||
'result': _$AuthResultEnumMap[instance.result],
|
||||
'device': instance.device?.toJson(),
|
||||
};
|
||||
|
||||
const _$AuthResultEnumMap = {
|
||||
AuthResult.success: 'Success',
|
||||
AuthResult.failure: 'Failure',
|
||||
@@ -137,59 +192,320 @@ Map<String, dynamic> _$CreateMediaItem$MutationToJson(
|
||||
'createMediaItem': instance.createMediaItem?.toJson(),
|
||||
};
|
||||
|
||||
Me$Query$User _$Me$Query$UserFromJson(Map<String, dynamic> json) {
|
||||
return Me$Query$User()
|
||||
MediaItems$Query$MediaItemResponse$MediaItem
|
||||
_$MediaItems$Query$MediaItemResponse$MediaItemFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return MediaItems$Query$MediaItemResponse$MediaItem()
|
||||
..id = json['id'] as String
|
||||
..fileName = json['fileName'] as String
|
||||
..latitude = (json['latitude'] as num)?.toDouble()
|
||||
..longitude = (json['longitude'] as num)?.toDouble()
|
||||
..isVideo = json['isVideo'] as bool
|
||||
..width = json['width'] as int
|
||||
..height = json['height'] as int
|
||||
..origName = json['origName'] as String
|
||||
..createdAt = json['createdAt'] == null
|
||||
? null
|
||||
: DateTime.parse(json['createdAt'] as String)
|
||||
..updatedAt = json['updatedAt'] == null
|
||||
? null
|
||||
: DateTime.parse(json['updatedAt'] as String)
|
||||
..email = json['email'] as String
|
||||
..username = json['username'] as String
|
||||
..firstName = json['firstName'] as String
|
||||
..lastName = json['lastName'] as String
|
||||
..role = _$enumDecodeNullable(_$RoleEnumMap, json['role'],
|
||||
unknownValue: Role.artemisUnknown)
|
||||
..authType = _$enumDecodeNullable(_$AuthTypeEnumMap, json['authType'],
|
||||
unknownValue: AuthType.artemisUnknown);
|
||||
: DateTime.parse(json['createdAt'] as String);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$Me$Query$UserToJson(Me$Query$User instance) =>
|
||||
Map<String, dynamic> _$MediaItems$Query$MediaItemResponse$MediaItemToJson(
|
||||
MediaItems$Query$MediaItemResponse$MediaItem instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'fileName': instance.fileName,
|
||||
'latitude': instance.latitude,
|
||||
'longitude': instance.longitude,
|
||||
'isVideo': instance.isVideo,
|
||||
'width': instance.width,
|
||||
'height': instance.height,
|
||||
'origName': instance.origName,
|
||||
'createdAt': instance.createdAt?.toIso8601String(),
|
||||
'updatedAt': instance.updatedAt?.toIso8601String(),
|
||||
'email': instance.email,
|
||||
'username': instance.username,
|
||||
'firstName': instance.firstName,
|
||||
'lastName': instance.lastName,
|
||||
'role': _$RoleEnumMap[instance.role],
|
||||
'authType': _$AuthTypeEnumMap[instance.authType],
|
||||
};
|
||||
|
||||
const _$RoleEnumMap = {
|
||||
Role.admin: 'Admin',
|
||||
Role.user: 'User',
|
||||
Role.artemisUnknown: 'ARTEMIS_UNKNOWN',
|
||||
};
|
||||
|
||||
const _$AuthTypeEnumMap = {
|
||||
AuthType.local: 'Local',
|
||||
AuthType.ldap: 'LDAP',
|
||||
AuthType.artemisUnknown: 'ARTEMIS_UNKNOWN',
|
||||
};
|
||||
|
||||
Me$Query _$Me$QueryFromJson(Map<String, dynamic> json) {
|
||||
return Me$Query()
|
||||
..me = json['me'] == null
|
||||
? null
|
||||
: Me$Query$User.fromJson(json['me'] as Map<String, dynamic>);
|
||||
MediaItems$Query$MediaItemResponse$PageResponse
|
||||
_$MediaItems$Query$MediaItemResponse$PageResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return MediaItems$Query$MediaItemResponse$PageResponse()
|
||||
..size = json['size'] as int
|
||||
..page = json['page'] as int
|
||||
..total = json['total'] as int;
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$Me$QueryToJson(Me$Query instance) => <String, dynamic>{
|
||||
'me': instance.me?.toJson(),
|
||||
Map<String, dynamic> _$MediaItems$Query$MediaItemResponse$PageResponseToJson(
|
||||
MediaItems$Query$MediaItemResponse$PageResponse instance) =>
|
||||
<String, dynamic>{
|
||||
'size': instance.size,
|
||||
'page': instance.page,
|
||||
'total': instance.total,
|
||||
};
|
||||
|
||||
MediaItems$Query$MediaItemResponse _$MediaItems$Query$MediaItemResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return MediaItems$Query$MediaItemResponse()
|
||||
..data = (json['data'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: MediaItems$Query$MediaItemResponse$MediaItem.fromJson(
|
||||
e as Map<String, dynamic>))
|
||||
?.toList()
|
||||
..page = json['page'] == null
|
||||
? null
|
||||
: MediaItems$Query$MediaItemResponse$PageResponse.fromJson(
|
||||
json['page'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$MediaItems$Query$MediaItemResponseToJson(
|
||||
MediaItems$Query$MediaItemResponse instance) =>
|
||||
<String, dynamic>{
|
||||
'data': instance.data?.map((e) => e?.toJson())?.toList(),
|
||||
'page': instance.page?.toJson(),
|
||||
};
|
||||
|
||||
MediaItems$Query _$MediaItems$QueryFromJson(Map<String, dynamic> json) {
|
||||
return MediaItems$Query()
|
||||
..mediaItems = json['mediaItems'] == null
|
||||
? null
|
||||
: MediaItems$Query$MediaItemResponse.fromJson(
|
||||
json['mediaItems'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$MediaItems$QueryToJson(MediaItems$Query instance) =>
|
||||
<String, dynamic>{
|
||||
'mediaItems': instance.mediaItems?.toJson(),
|
||||
};
|
||||
|
||||
TimeFilter _$TimeFilterFromJson(Map<String, dynamic> json) {
|
||||
return TimeFilter(
|
||||
equalTo: json['equalTo'] == null
|
||||
? null
|
||||
: DateTime.parse(json['equalTo'] as String),
|
||||
notEqualTo: json['notEqualTo'] == null
|
||||
? null
|
||||
: DateTime.parse(json['notEqualTo'] as String),
|
||||
lessThan: json['lessThan'] == null
|
||||
? null
|
||||
: DateTime.parse(json['lessThan'] as String),
|
||||
lessThanOrEqualTo: json['lessThanOrEqualTo'] == null
|
||||
? null
|
||||
: DateTime.parse(json['lessThanOrEqualTo'] as String),
|
||||
greaterThan: json['greaterThan'] == null
|
||||
? null
|
||||
: DateTime.parse(json['greaterThan'] as String),
|
||||
greaterThanOrEqualTo: json['greaterThanOrEqualTo'] == null
|
||||
? null
|
||||
: DateTime.parse(json['greaterThanOrEqualTo'] as String),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$TimeFilterToJson(TimeFilter instance) =>
|
||||
<String, dynamic>{
|
||||
'equalTo': instance.equalTo?.toIso8601String(),
|
||||
'notEqualTo': instance.notEqualTo?.toIso8601String(),
|
||||
'lessThan': instance.lessThan?.toIso8601String(),
|
||||
'lessThanOrEqualTo': instance.lessThanOrEqualTo?.toIso8601String(),
|
||||
'greaterThan': instance.greaterThan?.toIso8601String(),
|
||||
'greaterThanOrEqualTo': instance.greaterThanOrEqualTo?.toIso8601String(),
|
||||
};
|
||||
|
||||
FloatFilter _$FloatFilterFromJson(Map<String, dynamic> json) {
|
||||
return FloatFilter(
|
||||
equalTo: (json['equalTo'] as num)?.toDouble(),
|
||||
notEqualTo: (json['notEqualTo'] as num)?.toDouble(),
|
||||
lessThan: (json['lessThan'] as num)?.toDouble(),
|
||||
lessThanOrEqualTo: (json['lessThanOrEqualTo'] as num)?.toDouble(),
|
||||
greaterThan: (json['greaterThan'] as num)?.toDouble(),
|
||||
greaterThanOrEqualTo: (json['greaterThanOrEqualTo'] as num)?.toDouble(),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$FloatFilterToJson(FloatFilter instance) =>
|
||||
<String, dynamic>{
|
||||
'equalTo': instance.equalTo,
|
||||
'notEqualTo': instance.notEqualTo,
|
||||
'lessThan': instance.lessThan,
|
||||
'lessThanOrEqualTo': instance.lessThanOrEqualTo,
|
||||
'greaterThan': instance.greaterThan,
|
||||
'greaterThanOrEqualTo': instance.greaterThanOrEqualTo,
|
||||
};
|
||||
|
||||
BooleanFilter _$BooleanFilterFromJson(Map<String, dynamic> json) {
|
||||
return BooleanFilter(
|
||||
equalTo: json['equalTo'] as bool,
|
||||
notEqualTo: json['notEqualTo'] as bool,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$BooleanFilterToJson(BooleanFilter instance) =>
|
||||
<String, dynamic>{
|
||||
'equalTo': instance.equalTo,
|
||||
'notEqualTo': instance.notEqualTo,
|
||||
};
|
||||
|
||||
IDFilter _$IDFilterFromJson(Map<String, dynamic> json) {
|
||||
return IDFilter(
|
||||
equalTo: json['equalTo'] as String,
|
||||
notEqualTo: json['notEqualTo'] as String,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$IDFilterToJson(IDFilter instance) => <String, dynamic>{
|
||||
'equalTo': instance.equalTo,
|
||||
'notEqualTo': instance.notEqualTo,
|
||||
};
|
||||
|
||||
StringFilter _$StringFilterFromJson(Map<String, dynamic> json) {
|
||||
return StringFilter(
|
||||
equalTo: json['equalTo'] as String,
|
||||
notEqualTo: json['notEqualTo'] as String,
|
||||
startsWith: json['startsWith'] as String,
|
||||
notStartsWith: json['notStartsWith'] as String,
|
||||
endsWith: json['endsWith'] as String,
|
||||
notEndsWith: json['notEndsWith'] as String,
|
||||
contains: json['contains'] as String,
|
||||
notContains: json['notContains'] as String,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$StringFilterToJson(StringFilter instance) =>
|
||||
<String, dynamic>{
|
||||
'equalTo': instance.equalTo,
|
||||
'notEqualTo': instance.notEqualTo,
|
||||
'startsWith': instance.startsWith,
|
||||
'notStartsWith': instance.notStartsWith,
|
||||
'endsWith': instance.endsWith,
|
||||
'notEndsWith': instance.notEndsWith,
|
||||
'contains': instance.contains,
|
||||
'notContains': instance.notContains,
|
||||
};
|
||||
|
||||
MediaItemFilter _$MediaItemFilterFromJson(Map<String, dynamic> json) {
|
||||
return MediaItemFilter(
|
||||
id: json['id'] == null
|
||||
? null
|
||||
: IDFilter.fromJson(json['id'] as Map<String, dynamic>),
|
||||
createdAt: json['createdAt'] == null
|
||||
? null
|
||||
: TimeFilter.fromJson(json['createdAt'] as Map<String, dynamic>),
|
||||
updatedAt: json['updatedAt'] == null
|
||||
? null
|
||||
: TimeFilter.fromJson(json['updatedAt'] as Map<String, dynamic>),
|
||||
exifDate: json['exifDate'] == null
|
||||
? null
|
||||
: TimeFilter.fromJson(json['exifDate'] as Map<String, dynamic>),
|
||||
latitude: json['latitude'] == null
|
||||
? null
|
||||
: FloatFilter.fromJson(json['latitude'] as Map<String, dynamic>),
|
||||
longitude: json['longitude'] == null
|
||||
? null
|
||||
: FloatFilter.fromJson(json['longitude'] as Map<String, dynamic>),
|
||||
isVideo: json['isVideo'] == null
|
||||
? null
|
||||
: BooleanFilter.fromJson(json['isVideo'] as Map<String, dynamic>),
|
||||
origName: json['origName'] == null
|
||||
? null
|
||||
: StringFilter.fromJson(json['origName'] as Map<String, dynamic>),
|
||||
tags: json['tags'] == null
|
||||
? null
|
||||
: TagFilter.fromJson(json['tags'] as Map<String, dynamic>),
|
||||
albums: json['albums'] == null
|
||||
? null
|
||||
: AlbumFilter.fromJson(json['albums'] as Map<String, dynamic>),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$MediaItemFilterToJson(MediaItemFilter instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id?.toJson(),
|
||||
'createdAt': instance.createdAt?.toJson(),
|
||||
'updatedAt': instance.updatedAt?.toJson(),
|
||||
'exifDate': instance.exifDate?.toJson(),
|
||||
'latitude': instance.latitude?.toJson(),
|
||||
'longitude': instance.longitude?.toJson(),
|
||||
'isVideo': instance.isVideo?.toJson(),
|
||||
'origName': instance.origName?.toJson(),
|
||||
'tags': instance.tags?.toJson(),
|
||||
'albums': instance.albums?.toJson(),
|
||||
};
|
||||
|
||||
TagFilter _$TagFilterFromJson(Map<String, dynamic> json) {
|
||||
return TagFilter(
|
||||
id: json['id'] == null
|
||||
? null
|
||||
: IDFilter.fromJson(json['id'] as Map<String, dynamic>),
|
||||
createdAt: json['createdAt'] == null
|
||||
? null
|
||||
: TimeFilter.fromJson(json['createdAt'] as Map<String, dynamic>),
|
||||
updatedAt: json['updatedAt'] == null
|
||||
? null
|
||||
: TimeFilter.fromJson(json['updatedAt'] as Map<String, dynamic>),
|
||||
name: json['name'] == null
|
||||
? null
|
||||
: StringFilter.fromJson(json['name'] as Map<String, dynamic>),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$TagFilterToJson(TagFilter instance) => <String, dynamic>{
|
||||
'id': instance.id?.toJson(),
|
||||
'createdAt': instance.createdAt?.toJson(),
|
||||
'updatedAt': instance.updatedAt?.toJson(),
|
||||
'name': instance.name?.toJson(),
|
||||
};
|
||||
|
||||
AlbumFilter _$AlbumFilterFromJson(Map<String, dynamic> json) {
|
||||
return AlbumFilter(
|
||||
id: json['id'] == null
|
||||
? null
|
||||
: IDFilter.fromJson(json['id'] as Map<String, dynamic>),
|
||||
createdAt: json['createdAt'] == null
|
||||
? null
|
||||
: TimeFilter.fromJson(json['createdAt'] as Map<String, dynamic>),
|
||||
updatedAt: json['updatedAt'] == null
|
||||
? null
|
||||
: TimeFilter.fromJson(json['updatedAt'] as Map<String, dynamic>),
|
||||
name: json['name'] == null
|
||||
? null
|
||||
: StringFilter.fromJson(json['name'] as Map<String, dynamic>),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$AlbumFilterToJson(AlbumFilter instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id?.toJson(),
|
||||
'createdAt': instance.createdAt?.toJson(),
|
||||
'updatedAt': instance.updatedAt?.toJson(),
|
||||
'name': instance.name?.toJson(),
|
||||
};
|
||||
|
||||
Page _$PageFromJson(Map<String, dynamic> json) {
|
||||
return Page(
|
||||
size: json['size'] as int,
|
||||
page: json['page'] as int,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$PageToJson(Page instance) => <String, dynamic>{
|
||||
'size': instance.size,
|
||||
'page': instance.page,
|
||||
};
|
||||
|
||||
Order _$OrderFromJson(Map<String, dynamic> json) {
|
||||
return Order(
|
||||
by: json['by'] as String,
|
||||
direction: _$enumDecodeNullable(_$OrderDirectionEnumMap, json['direction'],
|
||||
unknownValue: OrderDirection.artemisUnknown),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$OrderToJson(Order instance) => <String, dynamic>{
|
||||
'by': instance.by,
|
||||
'direction': _$OrderDirectionEnumMap[instance.direction],
|
||||
};
|
||||
|
||||
const _$OrderDirectionEnumMap = {
|
||||
OrderDirection.asc: 'ASC',
|
||||
OrderDirection.desc: 'DESC',
|
||||
OrderDirection.artemisUnknown: 'ARTEMIS_UNKNOWN',
|
||||
};
|
||||
|
||||
LoginArguments _$LoginArgumentsFromJson(Map<String, dynamic> json) {
|
||||
@@ -219,3 +535,25 @@ Map<String, dynamic> _$CreateMediaItemArgumentsToJson(
|
||||
<String, dynamic>{
|
||||
'file': fromDartMultipartFileToGraphQLUpload(instance.file),
|
||||
};
|
||||
|
||||
MediaItemsArguments _$MediaItemsArgumentsFromJson(Map<String, dynamic> json) {
|
||||
return MediaItemsArguments(
|
||||
order: json['order'] == null
|
||||
? null
|
||||
: Order.fromJson(json['order'] as Map<String, dynamic>),
|
||||
page: json['page'] == null
|
||||
? null
|
||||
: Page.fromJson(json['page'] as Map<String, dynamic>),
|
||||
filter: json['filter'] == null
|
||||
? null
|
||||
: MediaItemFilter.fromJson(json['filter'] as Map<String, dynamic>),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$MediaItemsArgumentsToJson(
|
||||
MediaItemsArguments instance) =>
|
||||
<String, dynamic>{
|
||||
'order': instance.order?.toJson(),
|
||||
'page': instance.page?.toJson(),
|
||||
'filter': instance.filter?.toJson(),
|
||||
};
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
|
||||
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
|
||||
import 'package:imagini/blocs/home_bloc.dart';
|
||||
import 'package:imagini/core/app_provider.dart';
|
||||
|
||||
class HomeScreen extends StatefulWidget {
|
||||
static const String PATH = '/Home';
|
||||
@@ -14,12 +19,26 @@ class HomeScreen extends StatefulWidget {
|
||||
|
||||
class _HomeScreenState extends State<HomeScreen> {
|
||||
|
||||
// HomeBloc bloc;
|
||||
HomeBloc bloc;
|
||||
|
||||
int _currentIndex = 0;
|
||||
int _totalLength = 1;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_init();
|
||||
|
||||
return PlatformScaffold(
|
||||
body: _buildBody(),
|
||||
bottomNavBar: _buildNavBar()
|
||||
);
|
||||
}
|
||||
|
||||
void _init(){
|
||||
// if(null == bloc){
|
||||
// bloc = HomeBloc(AppProvider.getApplication(context));
|
||||
// }
|
||||
if(bloc != null)
|
||||
return;
|
||||
|
||||
bloc = HomeBloc(AppProvider.getApplication(context));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -28,33 +47,61 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
// bloc.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_init();
|
||||
Widget _buildBody() {
|
||||
var widgetMap = [
|
||||
<Widget>[
|
||||
_buildAppBar("Gallery"),
|
||||
_buildGridView()
|
||||
],
|
||||
<Widget>[
|
||||
_buildAppBar("Albums"),
|
||||
SliverToBoxAdapter()
|
||||
],
|
||||
<Widget>[
|
||||
_buildAppBar("Settings"),
|
||||
SliverToBoxAdapter()
|
||||
],
|
||||
];
|
||||
return CustomScrollView(
|
||||
shrinkWrap: true,
|
||||
slivers: widgetMap[_currentIndex],
|
||||
);
|
||||
}
|
||||
|
||||
return PlatformScaffold(
|
||||
body: _buildGridView(),
|
||||
bottomNavBar: _buildNavBar()
|
||||
Widget _buildAppBar(String title) {
|
||||
return SliverAppBar(
|
||||
title: new Text(title),
|
||||
pinned: false,
|
||||
snap: false,
|
||||
floating: true,
|
||||
leading: PlatformIconButton(
|
||||
icon: Icon(PlatformIcons(context).person),
|
||||
),
|
||||
actions: <Widget>[
|
||||
PlatformIconButton(
|
||||
icon: Icon(PlatformIcons(context).search),
|
||||
),
|
||||
PlatformIconButton(
|
||||
icon: Icon(PlatformIcons(context).add),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildNavBar() {
|
||||
return PlatformNavBar(
|
||||
currentIndex: 0,
|
||||
itemChanged: (index) => setState(
|
||||
() {
|
||||
// _selectedTabIndex = index;
|
||||
print(index);
|
||||
},
|
||||
),
|
||||
currentIndex: _currentIndex,
|
||||
itemChanged: (index) => setState(() {
|
||||
_currentIndex = index;
|
||||
}),
|
||||
items: [
|
||||
BottomNavigationBarItem(
|
||||
label: "Gallery",
|
||||
icon: Icon(PlatformIcons(context).collections),
|
||||
label: "Photos",
|
||||
icon: Icon(isMaterial(context) ? Icons.insert_photo : CupertinoIcons.photo),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
label: "Me",
|
||||
icon: Icon(PlatformIcons(context).person),
|
||||
label: "Albums",
|
||||
icon: Icon(isMaterial(context) ? Icons.collections : CupertinoIcons.photo_on_rectangle),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
label: "Settings",
|
||||
@@ -64,42 +111,59 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _appLoading(){
|
||||
return Center(
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: 500),
|
||||
child: Container(
|
||||
margin: EdgeInsets.fromLTRB(50, 0, 50, 0),
|
||||
height: 370,
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
PlatformCircularProgressIndicator()
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildGridView() {
|
||||
// return GridView.builder(
|
||||
// itemCount: 5,
|
||||
// gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
|
||||
// childAspectRatio: (1 / 1),
|
||||
// crossAxisCount: 2),
|
||||
// itemBuilder: (BuildContext context, int index) {
|
||||
// return _buildCard("https://i.imgur.com/CgSGqUz.jpeg");
|
||||
// }
|
||||
// );
|
||||
MediaQueryData queryData = MediaQuery.of(context);
|
||||
|
||||
// Can change this to change desired image size
|
||||
final int desiredContentWidth = 500;
|
||||
|
||||
return new StaggeredGridView.countBuilder(
|
||||
crossAxisCount: 4,
|
||||
itemCount: 80,
|
||||
itemBuilder: (BuildContext context, int index) => _buildCard("https://i.imgur.com/CgSGqUz.jpeg"),
|
||||
// itemBuilder: (BuildContext context, int index) => new Container(
|
||||
// color: Colors.green,
|
||||
// child: new Center(
|
||||
// child: new CircleAvatar(
|
||||
// backgroundColor: Colors.white,
|
||||
// child: new Text('$index'),
|
||||
// ),
|
||||
// )),
|
||||
staggeredTileBuilder: (int index) =>
|
||||
// new StaggeredTile.count(2, index.isEven ? 2 : 1),
|
||||
new StaggeredTile.fit(2),
|
||||
return SliverStaggeredGrid.extentBuilder(
|
||||
itemCount: _totalLength,
|
||||
mainAxisSpacing: 4.0,
|
||||
crossAxisSpacing: 4.0,
|
||||
maxCrossAxisExtent: 500 / queryData.devicePixelRatio,
|
||||
staggeredTileBuilder: (int index) => new StaggeredTile.fit(1),
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return _buildCard(index, desiredContentWidth);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildCard(charImageUrl) {
|
||||
return new Image.network(
|
||||
charImageUrl,
|
||||
fit: BoxFit.contain,
|
||||
Widget _buildCard(index, derivedContentWidth) {
|
||||
return FutureBuilder<CachedNetworkImage>(
|
||||
future: bloc.getMedia(index, derivedContentWidth),
|
||||
builder: (context, snapshot) {
|
||||
if (!snapshot.hasData)
|
||||
return SizedBox(width: 500, height: 500);
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (_totalLength == bloc.totalMediaItems)
|
||||
return;
|
||||
|
||||
setState(() {
|
||||
_totalLength = bloc.totalMediaItems;
|
||||
});
|
||||
});
|
||||
|
||||
return snapshot.data;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fluro/fluro.dart';
|
||||
|
||||
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
|
||||
|
||||
import 'package:imagini/blocs/login_bloc.dart';
|
||||
import 'package:imagini/core/app_provider.dart';
|
||||
|
||||
class LoginScreen extends StatefulWidget {
|
||||
static const String PATH = '/Login';
|
||||
static const String PATH = '/';
|
||||
|
||||
LoginScreen({Key key}) : super(key: key);
|
||||
|
||||
@@ -16,7 +17,41 @@ class LoginScreen extends StatefulWidget {
|
||||
|
||||
class _LoginScreenState extends State<LoginScreen> {
|
||||
|
||||
// LoginBloc bloc;
|
||||
LoginBloc bloc;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_init();
|
||||
|
||||
return Scaffold(
|
||||
body: StreamBuilder<bool>(
|
||||
stream: bloc.authenticatedResult,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.data == null || snapshot.data == true)
|
||||
return _appLoading();
|
||||
return _appLogin();
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void _init(){
|
||||
if(bloc != null)
|
||||
return;
|
||||
|
||||
bloc = LoginBloc(AppProvider.getApplication(context));
|
||||
bloc.authenticatedResult.listen((bool status) {
|
||||
if (status)
|
||||
AppProvider.getRouter(context).navigateTo(context, "/Home", transition: TransitionType.fadeIn);
|
||||
});
|
||||
|
||||
bloc.loginResult.listen((bool status) {
|
||||
if (status == null || status == false)
|
||||
return;
|
||||
|
||||
AppProvider.getRouter(context).navigateTo(context, "/Home", transition: TransitionType.fadeIn);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
@@ -24,46 +59,90 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
// bloc.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_init();
|
||||
Widget _appLoading(){
|
||||
return Center(
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: 500),
|
||||
child: Container(
|
||||
margin: EdgeInsets.fromLTRB(50, 0, 50, 0),
|
||||
height: 275,
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
child: Image(image: AssetImage('assets/imagini_full.png')),
|
||||
width: 175,
|
||||
margin: EdgeInsets.fromLTRB(0, 0, 0, 50),
|
||||
),
|
||||
PlatformCircularProgressIndicator()
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
Widget _appLogin(){
|
||||
TextEditingController serverController = new TextEditingController();
|
||||
TextEditingController userController = new TextEditingController();
|
||||
TextEditingController passwordController = new TextEditingController();
|
||||
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
return Center(
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: 500),
|
||||
child: Container(
|
||||
margin: EdgeInsets.fromLTRB(50, 0, 50, 0),
|
||||
height: 500,
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
child: FittedBox(
|
||||
fit: BoxFit.contain,
|
||||
child: const FlutterLogo(),
|
||||
),
|
||||
child: Image(image: AssetImage('assets/imagini_full.png')),
|
||||
width: 175,
|
||||
margin: EdgeInsets.fromLTRB(0, 0, 0, 50),
|
||||
),
|
||||
Expanded(
|
||||
child: TextField(
|
||||
child: TextFormField(
|
||||
controller: serverController,
|
||||
validator: (value) {
|
||||
if (value.isEmpty) {
|
||||
return 'Please enter server address';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Server Address'
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: TextField(
|
||||
child: TextFormField(
|
||||
controller: userController,
|
||||
validator: (value) {
|
||||
if (value.isEmpty) {
|
||||
return 'Please enter username or email';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Username / Email'
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: TextField(
|
||||
child: TextFormField(
|
||||
obscureText: true,
|
||||
enableSuggestions: false,
|
||||
autocorrect: false,
|
||||
controller: passwordController,
|
||||
validator: (value) {
|
||||
if (value.isEmpty) {
|
||||
return 'Please enter password';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Password'
|
||||
),
|
||||
@@ -73,11 +152,31 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
width: double.infinity,
|
||||
child: PlatformButton(
|
||||
onPressed: () {
|
||||
AppProvider.getRouter(context).navigateTo(context, "/Home", transition: TransitionType.fadeIn);
|
||||
if (!_formKey.currentState.validate())
|
||||
return;
|
||||
bloc.attemptLogin(userController.text, passwordController.text, serverController.text);
|
||||
},
|
||||
child: Text('Login')
|
||||
),
|
||||
),
|
||||
|
||||
StreamBuilder<bool>(
|
||||
stream: bloc.loginResult,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.data == null || snapshot.data == true)
|
||||
return Container();
|
||||
|
||||
return Expanded(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.fromLTRB(20, 20, 20, 20),
|
||||
child: Text(
|
||||
"Login Failed",
|
||||
style: TextStyle(color: Colors.red),
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -85,10 +184,4 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _init(){
|
||||
// if(null == bloc){
|
||||
// bloc = LoginBloc(AppProvider.getApplication(context));
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
|
||||
import 'package:fluro/fluro.dart';
|
||||
|
||||
import 'package:imagini/core/app_provider.dart';
|
||||
import 'package:imagini/blocs/splash_bloc.dart';
|
||||
import 'package:imagini/graphql/imagini_graphql.dart';
|
||||
|
||||
class SplashScreen extends StatefulWidget {
|
||||
static const String PATH = '/';
|
||||
|
||||
SplashScreen({Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_SplashScreenState createState() => _SplashScreenState();
|
||||
}
|
||||
|
||||
class _SplashScreenState extends State<SplashScreen> {
|
||||
|
||||
SplashBloc bloc;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
bloc.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_init();
|
||||
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: 500),
|
||||
child: Container(
|
||||
margin: EdgeInsets.fromLTRB(50, 0, 50, 0),
|
||||
height: 270,
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
child: FittedBox(
|
||||
fit: BoxFit.contain,
|
||||
child: const FlutterLogo(),
|
||||
),
|
||||
width: 175,
|
||||
margin: EdgeInsets.fromLTRB(0, 0, 0, 50),
|
||||
),
|
||||
PlatformCircularProgressIndicator()
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _init(){
|
||||
if(null == bloc){
|
||||
bloc = SplashBloc(AppProvider.getApplication(context));
|
||||
bloc.loginResult.listen((Login$Query$AuthResponse lr) {
|
||||
if (lr.result == AuthResult.success) {
|
||||
AppProvider.getRouter(context).navigateTo(context, "/Home", transition: TransitionType.fadeIn);
|
||||
} else {
|
||||
AppProvider.getRouter(context).navigateTo(context, "/Login", transition: TransitionType.fadeIn);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,12 +30,12 @@ packages:
|
||||
source: hosted
|
||||
version: "1.6.0"
|
||||
artemis:
|
||||
dependency: "direct main"
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: artemis
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.18.3"
|
||||
version: "6.18.4"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -43,13 +43,6 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.5.0-nullsafety.3"
|
||||
bloc:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: bloc
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.1.1"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -113,6 +106,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "8.0.0-nullsafety.0"
|
||||
cached_network_image:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: cached_network_image
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.5.0"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -246,13 +246,6 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.0.0-nullsafety.4"
|
||||
file_picker:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: file_picker
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.6"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -272,18 +265,32 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_bloc:
|
||||
dependency: "direct main"
|
||||
flutter_blurhash:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_bloc
|
||||
name: flutter_blurhash
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.1.2"
|
||||
version: "0.5.0"
|
||||
flutter_cache_manager:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_cache_manager
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
flutter_driver:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_launcher_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_launcher_icons
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.8.1"
|
||||
flutter_platform_widgets:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -291,13 +298,6 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.80.0-beta.0"
|
||||
flutter_plugin_android_lifecycle:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_plugin_android_lifecycle
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.11"
|
||||
flutter_secure_storage:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -439,6 +439,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.4"
|
||||
image:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.19"
|
||||
integration_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
@@ -500,13 +507,6 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
nested:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: nested
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.0.4"
|
||||
node_interop:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -528,6 +528,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.7"
|
||||
octo_image:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: octo_image
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
package_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -584,6 +591,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
petitparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: petitparser
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -612,13 +626,6 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.0.0-nullsafety.4"
|
||||
provider:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: provider
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.3.3"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -647,48 +654,6 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.24.1"
|
||||
shared_preferences:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: shared_preferences
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.5.12+4"
|
||||
shared_preferences_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_linux
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.0.2+4"
|
||||
shared_preferences_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_macos
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.0.1+11"
|
||||
shared_preferences_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
shared_preferences_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_web
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.2+7"
|
||||
shared_preferences_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.0.2+3"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -722,6 +687,20 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.0-nullsafety.4"
|
||||
sqflite:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.2+3"
|
||||
sqflite_common:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite_common
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.3+1"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -757,6 +736,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.0"
|
||||
synchronized:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: synchronized
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.2.0+2"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -785,48 +771,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0-nullsafety.5"
|
||||
url_launcher:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: url_launcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.7.10"
|
||||
url_launcher_linux:
|
||||
uuid:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_linux
|
||||
name: uuid
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.0.1+4"
|
||||
url_launcher_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_macos
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.0.1+9"
|
||||
url_launcher_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.9"
|
||||
url_launcher_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_web
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.5+3"
|
||||
url_launcher_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.0.1+3"
|
||||
version: "2.2.2"
|
||||
uuid_enhanced:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -890,6 +841,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.2"
|
||||
xml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xml
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.5.1"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -899,4 +857,4 @@ packages:
|
||||
version: "2.2.1"
|
||||
sdks:
|
||||
dart: ">=2.12.0-0.0 <3.0.0"
|
||||
flutter: ">=1.22.0"
|
||||
flutter: ">=1.22.2"
|
||||
|
||||
@@ -1,21 +1,8 @@
|
||||
name: imagini
|
||||
description: A new Flutter project.
|
||||
description: Imagini Client
|
||||
|
||||
# The following line prevents the package from being accidentally published to
|
||||
# pub.dev using `pub publish`. This is preferred for private packages.
|
||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
|
||||
# The following defines the version and build number for your application.
|
||||
# A version number is three numbers separated by dots, like 1.2.43
|
||||
# followed by an optional build number separated by a +.
|
||||
# Both the version and the builder number may be overridden in flutter
|
||||
# build by specifying --build-name and --build-number, respectively.
|
||||
# In Android, build-name is used as versionName while build-number used as versionCode.
|
||||
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
|
||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
version: 1.0.0+1
|
||||
version: 0.0.1
|
||||
|
||||
environment:
|
||||
sdk: ">=2.7.0 <3.0.0"
|
||||
@@ -28,17 +15,14 @@ dependencies:
|
||||
fluro: ^1.7.8
|
||||
equatable: ^1.2.5
|
||||
http: ^0.12.2
|
||||
shared_preferences: ^0.5.12+4
|
||||
flutter_secure_storage: ^3.3.5
|
||||
flutter_platform_widgets: ^0.80.0-beta.0
|
||||
flutter_bloc: ^6.1.1
|
||||
file_picker: ^2.1.5
|
||||
url_launcher: ^5.7.10
|
||||
cupertino_icons: ^1.0.1
|
||||
artemis: '>=6.0.0 <7.0.0' # only if you're using ArtemisClient!
|
||||
json_annotation: ^3.1.0
|
||||
meta: '>=1.0.0 <2.0.0' # only if you have non nullable fields
|
||||
meta: '>=1.0.0 <2.0.0'
|
||||
gql: '>=0.12.3 <1.0.0'
|
||||
cached_network_image: ^2.5.0
|
||||
cupertino_icons: ^1.0.1
|
||||
flutter_launcher_icons: ^0.8.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
@@ -49,44 +33,12 @@ dev_dependencies:
|
||||
build_runner: ^1.10.4
|
||||
json_serializable: ^3.5.0
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
||||
# The following section is specific to Flutter.
|
||||
flutter:
|
||||
|
||||
# The following line ensures that the Material Icons font is
|
||||
# included with your application, so that you can use the icons in
|
||||
# the material Icons class.
|
||||
uses-material-design: true
|
||||
assets:
|
||||
- assets/imagini_full.png
|
||||
|
||||
# To add assets to your application, add an assets section, like this:
|
||||
# assets:
|
||||
# - images/a_dot_burr.jpeg
|
||||
# - images/a_dot_ham.jpeg
|
||||
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/assets-and-images/#resolution-aware.
|
||||
|
||||
# For details regarding adding assets from package dependencies, see
|
||||
# https://flutter.dev/assets-and-images/#from-packages
|
||||
|
||||
# To add custom fonts to your application, add a fonts section here,
|
||||
# in this "flutter" section. Each entry in this list should have a
|
||||
# "family" key with the font family name, and a "fonts" key with a
|
||||
# list giving the asset and other descriptors for the font. For
|
||||
# example:
|
||||
# fonts:
|
||||
# - family: Schyler
|
||||
# fonts:
|
||||
# - asset: fonts/Schyler-Regular.ttf
|
||||
# - asset: fonts/Schyler-Italic.ttf
|
||||
# style: italic
|
||||
# - family: Trajan Pro
|
||||
# fonts:
|
||||
# - asset: fonts/TrajanPro.ttf
|
||||
# - asset: fonts/TrajanPro_Bold.ttf
|
||||
# weight: 700
|
||||
#
|
||||
# For details regarding fonts from package dependencies,
|
||||
# see https://flutter.dev/custom-fonts/#from-packages
|
||||
flutter_icons:
|
||||
android: "launcher_icon"
|
||||
ios: true
|
||||
image_path: "assets/icon/icon.png"
|
||||
|
||||
@@ -158,6 +158,8 @@ type MediaItem {
|
||||
isVideo: Boolean! @meta(gorm: "default:false;not null")
|
||||
fileName: String! @meta(gorm: "not null")
|
||||
origName: String! @meta(gorm: "not null")
|
||||
width: Int! @meta(gorm: "not null")
|
||||
height: Int! @meta(gorm: "not null")
|
||||
tags: [Tag] @meta(gorm: "many2many:media_tags;foreignKey:ID,UserID;References:ID")
|
||||
albums: [Album] @meta(gorm: "many2many:media_albums;foreignKey:ID,UserID;Refrences:ID")
|
||||
userID: ID! @meta(gorm: "not null")
|
||||
|
||||