mirror of
https://github.com/ecency/ecency-mobile.git
synced 2024-12-28 07:55:08 +03:00
Merge pull request #68 from esteemapp/feature/editorScreen
Feature/editor screen
This commit is contained in:
commit
15bf0748be
@ -1238,6 +1238,13 @@
|
||||
remoteRef = 3DAD3EAE1DF850E9000B6D8A /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
478F70212178F4DC00AB7885 /* libReact-Native-Webview-Bridge.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = "libReact-Native-Webview-Bridge.a";
|
||||
remoteRef = 478F70202178F4DC00AB7885 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
@ -1438,11 +1445,6 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"-ObjC",
|
||||
@ -1472,11 +1474,6 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"-ObjC",
|
||||
@ -1565,11 +1562,6 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"-ObjC",
|
||||
@ -1607,11 +1599,6 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"-ObjC",
|
||||
@ -1648,11 +1635,6 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"-ObjC",
|
||||
@ -1689,11 +1671,6 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"-ObjC",
|
||||
|
@ -5,7 +5,7 @@
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>esteem</string>
|
||||
<string>eSteem</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
@ -38,7 +38,21 @@
|
||||
</dict>
|
||||
</dict>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string/>
|
||||
<string></string>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
<key>UIAppFonts</key>
|
||||
<array>
|
||||
<string>Entypo.ttf</string>
|
||||
|
85
package-lock.json
generated
85
package-lock.json
generated
@ -1512,7 +1512,7 @@
|
||||
"dependencies": {
|
||||
"chalk": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
||||
"requires": {
|
||||
"ansi-styles": "^2.2.1",
|
||||
@ -1705,7 +1705,7 @@
|
||||
},
|
||||
"babel-plugin-istanbul": {
|
||||
"version": "4.1.6",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz",
|
||||
"resolved": "http://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz",
|
||||
"integrity": "sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -1738,7 +1738,7 @@
|
||||
},
|
||||
"babel-plugin-syntax-object-rest-spread": {
|
||||
"version": "6.13.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz",
|
||||
"integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U="
|
||||
},
|
||||
"babel-plugin-syntax-trailing-function-commas": {
|
||||
@ -2291,7 +2291,7 @@
|
||||
},
|
||||
"browserify-aes": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
|
||||
"integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
|
||||
"requires": {
|
||||
"buffer-xor": "^1.0.3",
|
||||
@ -2600,7 +2600,7 @@
|
||||
},
|
||||
"color": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/color/-/color-1.0.3.tgz",
|
||||
"resolved": "http://registry.npmjs.org/color/-/color-1.0.3.tgz",
|
||||
"integrity": "sha1-5I6DLYXxTvaU+0aIEcLVz+cptV0=",
|
||||
"requires": {
|
||||
"color-convert": "^1.8.2",
|
||||
@ -2779,7 +2779,7 @@
|
||||
},
|
||||
"create-hash": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
|
||||
"integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
|
||||
"requires": {
|
||||
"cipher-base": "^1.0.1",
|
||||
@ -2791,7 +2791,7 @@
|
||||
},
|
||||
"create-hmac": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
|
||||
"resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
|
||||
"integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
|
||||
"requires": {
|
||||
"cipher-base": "^1.0.3",
|
||||
@ -2985,7 +2985,7 @@
|
||||
"dependencies": {
|
||||
"file-type": {
|
||||
"version": "3.9.0",
|
||||
"resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
|
||||
"integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek="
|
||||
},
|
||||
"get-stream": {
|
||||
@ -3856,7 +3856,7 @@
|
||||
},
|
||||
"events": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
|
||||
"resolved": "http://registry.npmjs.org/events/-/events-1.1.1.tgz",
|
||||
"integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ="
|
||||
},
|
||||
"evp_bytestokey": {
|
||||
@ -3958,7 +3958,7 @@
|
||||
},
|
||||
"external-editor": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
|
||||
"integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==",
|
||||
"requires": {
|
||||
"chardet": "^0.4.0",
|
||||
@ -4834,7 +4834,7 @@
|
||||
},
|
||||
"get-stream": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
|
||||
},
|
||||
"get-value": {
|
||||
@ -5350,7 +5350,7 @@
|
||||
},
|
||||
"is-builtin-module": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
|
||||
"integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
|
||||
"requires": {
|
||||
"builtin-modules": "^1.0.0"
|
||||
@ -5495,7 +5495,7 @@
|
||||
},
|
||||
"is-obj": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
|
||||
"resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
|
||||
"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
|
||||
"dev": true
|
||||
},
|
||||
@ -6983,12 +6983,12 @@
|
||||
},
|
||||
"json5": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
|
||||
"resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
|
||||
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE="
|
||||
},
|
||||
"jsonfile": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
|
||||
"integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
@ -7538,7 +7538,7 @@
|
||||
"dependencies": {
|
||||
"chalk": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -7584,7 +7584,7 @@
|
||||
"dependencies": {
|
||||
"chalk": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -7634,7 +7634,7 @@
|
||||
},
|
||||
"load-json-file": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
|
||||
"integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.2",
|
||||
@ -7653,9 +7653,9 @@
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.10",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
|
||||
"integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg=="
|
||||
"version": "4.17.11",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
|
||||
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
|
||||
},
|
||||
"lodash-es": {
|
||||
"version": "4.17.11",
|
||||
@ -8406,7 +8406,7 @@
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
|
||||
},
|
||||
"minipass": {
|
||||
@ -8454,7 +8454,7 @@
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||
"resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
@ -8462,7 +8462,7 @@
|
||||
"dependencies": {
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
||||
"resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
|
||||
}
|
||||
}
|
||||
@ -8573,9 +8573,14 @@
|
||||
"tween-functions": "^1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash": {
|
||||
"version": "4.17.10",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
|
||||
"integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg=="
|
||||
},
|
||||
"react-native-keyboard-aware-scroll-view": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-keyboard-aware-scroll-view/-/react-native-keyboard-aware-scroll-view-0.5.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/react-native-keyboard-aware-scroll-view/-/react-native-keyboard-aware-scroll-view-0.5.0.tgz",
|
||||
"integrity": "sha512-nGXsACZBCiWuwRrZy+UjiSJqb4tZ/6ePHUSY8M+09g4VfNm/ogvvWpwBa6B999NZ6DwhZTKBjVWeZxX9XG8bbQ==",
|
||||
"requires": {
|
||||
"prop-types": "^15.6.0",
|
||||
@ -8979,7 +8984,7 @@
|
||||
"dependencies": {
|
||||
"minimist": {
|
||||
"version": "0.0.10",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
|
||||
"resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
|
||||
"integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="
|
||||
},
|
||||
"wordwrap": {
|
||||
@ -9432,7 +9437,7 @@
|
||||
},
|
||||
"regexpp": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz",
|
||||
"integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==",
|
||||
"dev": true
|
||||
},
|
||||
@ -9871,14 +9876,6 @@
|
||||
"resolved": "https://registry.npmjs.org/react-native-linear-gradient/-/react-native-linear-gradient-2.4.2.tgz",
|
||||
"integrity": "sha512-6+efUAsLIn8jHwb861ftjNmw0QuIhKCeQ3vBgQvPDWDcdL1M7GbPmOUdATQfoPod+m+UGSjLf8Tez2QwYLAG+A=="
|
||||
},
|
||||
"react-native-markdown-editor": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/react-native-markdown-editor/-/react-native-markdown-editor-1.0.1.tgz",
|
||||
"integrity": "sha512-VUrRvg/Qm40cv5P6keShYQTqtkSk1IZo8RITuuzXldZo1gavOTHcaVe2OE4KHdGiiqrLMbL/mZj9NNt3I8FChA==",
|
||||
"requires": {
|
||||
"react-native-markdown-view": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"react-native-markdown-view": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/react-native-markdown-view/-/react-native-markdown-view-1.1.4.tgz",
|
||||
@ -9967,7 +9964,7 @@
|
||||
},
|
||||
"react-native-vector-icons": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-vector-icons/-/react-native-vector-icons-4.6.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/react-native-vector-icons/-/react-native-vector-icons-4.6.0.tgz",
|
||||
"integrity": "sha512-rpfhfPiXCK2PX1nrNhdxSMrEGB/Gw/SvKoPM0G2wAkSoqynnes19K0VYI+Up7DqR1rFIpE4hP2erpT1tNx2tfg==",
|
||||
"requires": {
|
||||
"lodash": "^4.0.0",
|
||||
@ -10067,7 +10064,7 @@
|
||||
},
|
||||
"react-redux": {
|
||||
"version": "5.0.7",
|
||||
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.0.7.tgz",
|
||||
"resolved": "http://registry.npmjs.org/react-redux/-/react-redux-5.0.7.tgz",
|
||||
"integrity": "sha512-5VI8EV5hdgNgyjfmWzBbdrqUkrVRKlyTKk1sGH3jzM2M2Mhj/seQgPXaz6gVAj2lz/nz688AdTqMO18Lr24Zhg==",
|
||||
"requires": {
|
||||
"hoist-non-react-statics": "^2.5.0",
|
||||
@ -10141,7 +10138,7 @@
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.3.6",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
||||
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
||||
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
@ -11031,7 +11028,7 @@
|
||||
},
|
||||
"sha.js": {
|
||||
"version": "2.4.11",
|
||||
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
|
||||
"resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
|
||||
"integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
|
||||
"requires": {
|
||||
"inherits": "^2.0.1",
|
||||
@ -11546,7 +11543,7 @@
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
@ -11746,7 +11743,7 @@
|
||||
},
|
||||
"load-json-file": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
|
||||
"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -11861,7 +11858,7 @@
|
||||
},
|
||||
"through": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||
"resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
|
||||
},
|
||||
"through2": {
|
||||
@ -12145,7 +12142,7 @@
|
||||
},
|
||||
"underscore.string": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz",
|
||||
"integrity": "sha1-jN2PusTi0uoefi6Al8QvRCKA+Fs="
|
||||
},
|
||||
"unicode-canonical-property-names-ecmascript": {
|
||||
@ -12494,7 +12491,7 @@
|
||||
},
|
||||
"wrap-ansi": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
|
||||
"integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
|
||||
"requires": {
|
||||
"string-width": "^1.0.1",
|
||||
|
10
package.json
10
package.json
@ -1,7 +1,12 @@
|
||||
{
|
||||
"name": "esteem",
|
||||
"name": "eSteem",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"rnpm": {
|
||||
"assets": [
|
||||
"./assets/fonts"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node node_modules/react-native/local-cli/cli.js start",
|
||||
"eject": "node node_modules/react-native/local-cli/cli.js eject",
|
||||
@ -20,6 +25,7 @@
|
||||
"@esteemapp/react-native-tags": "^1.3.1",
|
||||
"crypto-js": "^3.1.9-1",
|
||||
"dsteem": "^0.10.1",
|
||||
"lodash": "^4.17.11",
|
||||
"moment": "^2.22.2",
|
||||
"native-base": "^2.8.1",
|
||||
"react": "^16.6.0-alpha.8af6728",
|
||||
@ -29,7 +35,7 @@
|
||||
"react-native-html-renderer": "^1.0.0",
|
||||
"react-native-keyboard-aware-scroll-view": "^0.7.2",
|
||||
"react-native-linear-gradient": "^2.4.2",
|
||||
"react-native-markdown-editor": "^1.0.1",
|
||||
"react-native-markdown-view": "^1.1.4",
|
||||
"react-native-modal": "^6.5.0",
|
||||
"react-native-modal-dropdown": "^0.6.2",
|
||||
"react-native-modal-popover": "0.0.10",
|
||||
|
BIN
src/assets/Fonts/RobotoMono-Regular.ttf
Executable file
BIN
src/assets/Fonts/RobotoMono-Regular.ttf
Executable file
Binary file not shown.
@ -5,7 +5,15 @@ import NoPost from './view/noPostView';
|
||||
import PostPlaceHolder from './view/postPlaceHolderView';
|
||||
import TextWithIcon from './view/textWithIconView';
|
||||
import WalletLineItem from './view/walletLineItemView';
|
||||
import Chip from './view/chipView';
|
||||
|
||||
export {
|
||||
Card, GrayWrapper, LineBreak, NoPost, PostPlaceHolder, TextWithIcon, WalletLineItem,
|
||||
Card,
|
||||
GrayWrapper,
|
||||
Chip,
|
||||
LineBreak,
|
||||
NoPost,
|
||||
PostPlaceHolder,
|
||||
TextWithIcon,
|
||||
WalletLineItem,
|
||||
};
|
||||
|
17
src/components/basicUIElements/view/chipStyle.js
Normal file
17
src/components/basicUIElements/view/chipStyle.js
Normal file
@ -0,0 +1,17 @@
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
textInput: {
|
||||
color: '$white',
|
||||
fontSize: 10,
|
||||
backgroundColor: '#c1c5c7',
|
||||
borderRadius: 50,
|
||||
maxHeight: 18,
|
||||
padding: 5,
|
||||
paddingHorizontal: 10,
|
||||
marginRight: 8,
|
||||
},
|
||||
isPin: {
|
||||
backgroundColor: '$primaryBlue',
|
||||
},
|
||||
});
|
16
src/components/basicUIElements/view/chipView.js
Normal file
16
src/components/basicUIElements/view/chipView.js
Normal file
@ -0,0 +1,16 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import { TextInput } from 'react-native';
|
||||
import styles from './chipStyle';
|
||||
|
||||
const Chip = props => (
|
||||
<Fragment>
|
||||
<TextInput
|
||||
style={[styles.textInput, props.isPin && styles.isPin]}
|
||||
onChangeText={text => props.handleOnChange(text)}
|
||||
onBlur={() => props.handleOnBlur()}
|
||||
{...props}
|
||||
/>
|
||||
</Fragment>
|
||||
);
|
||||
|
||||
export default Chip;
|
@ -1,14 +1,14 @@
|
||||
import EStyleSheet from "react-native-extended-stylesheet";
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
circleButton: {
|
||||
alignItems: "center",
|
||||
backgroundColor: "$white",
|
||||
alignItems: 'center',
|
||||
backgroundColor: '$white',
|
||||
height: 60,
|
||||
width: 60,
|
||||
borderRadius: 60 / 2,
|
||||
justifyContent: "center",
|
||||
borderColor: "$primaryBlue",
|
||||
justifyContent: 'center',
|
||||
borderColor: '$primaryBlue',
|
||||
borderWidth: 1,
|
||||
},
|
||||
});
|
||||
|
@ -3,14 +3,13 @@ import { TouchableWithoutFeedback, Text, View } from 'react-native';
|
||||
|
||||
import styles from './textButtonStyles';
|
||||
|
||||
const TextButtonView = ({ text, onPress, style }) => (
|
||||
const TextButtonView = ({
|
||||
text, onPress, style, textStyle,
|
||||
}) => (
|
||||
<Fragment>
|
||||
<TouchableWithoutFeedback
|
||||
style={[styles.button, style]}
|
||||
onPress={() => onPress && onPress()}
|
||||
>
|
||||
<View>
|
||||
<Text style={styles.buttonText}>{text}</Text>
|
||||
<TouchableWithoutFeedback style={[styles.button]} onPress={() => onPress && onPress()}>
|
||||
<View style={style}>
|
||||
<Text style={[styles.buttonText, textStyle]}>{text}</Text>
|
||||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
</Fragment>
|
||||
|
@ -8,14 +8,14 @@ export default EStyleSheet.create({
|
||||
alignSelf: 'flex-start',
|
||||
height: 35,
|
||||
},
|
||||
dropdownText: {
|
||||
fontSize: 9,
|
||||
color: '$primaryDarkGray',
|
||||
marginLeft: 25,
|
||||
},
|
||||
// dropdownText: {
|
||||
// fontSize: 9,
|
||||
// color: '$primaryDarkGray',
|
||||
// marginLeft: 25,
|
||||
// },
|
||||
dropdownIcon: {
|
||||
fontSize: 18,
|
||||
color:"$iconColor",
|
||||
color: '$iconColor',
|
||||
marginLeft: 7,
|
||||
marginTop: 1,
|
||||
},
|
||||
|
@ -30,15 +30,16 @@ const renderDropdownRow = (rowData, rowID, highlighted) => (
|
||||
);
|
||||
|
||||
const DropdownButtonView = ({
|
||||
defaultText,
|
||||
iconName,
|
||||
options,
|
||||
onSelect,
|
||||
defaultIndex,
|
||||
children,
|
||||
style,
|
||||
isHasChildIcon,
|
||||
childIconWrapperStyle,
|
||||
children,
|
||||
defaultIndex,
|
||||
defaultText,
|
||||
iconStyle,
|
||||
iconName,
|
||||
isHasChildIcon,
|
||||
onSelect,
|
||||
options,
|
||||
style,
|
||||
}) => (
|
||||
<View style={styles.container}>
|
||||
<ModalDropdown
|
||||
@ -56,7 +57,10 @@ const DropdownButtonView = ({
|
||||
>
|
||||
{isHasChildIcon && (
|
||||
<View style={[styles.iconWrapper, childIconWrapperStyle && childIconWrapperStyle]}>
|
||||
<Ionicons style={styles.dropdownIcon} name={!iconName ? 'md-arrow-dropdown' : iconName} />
|
||||
<Ionicons
|
||||
style={[styles.dropdownIcon, iconStyle]}
|
||||
name={!iconName ? 'md-arrow-dropdown' : iconName}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
</ModalDropdown>
|
||||
|
5
src/components/editorElements/index.js
Normal file
5
src/components/editorElements/index.js
Normal file
@ -0,0 +1,5 @@
|
||||
import TitleArea from './titleArea/view/titleAreaView';
|
||||
import TagArea from './tagArea/view/tagAreaView';
|
||||
import TextArea from './textArea/view/textAreaView';
|
||||
|
||||
export { TitleArea, TagArea, TextArea };
|
21
src/components/editorElements/tagArea/view/tagAreaStyles.js
Normal file
21
src/components/editorElements/tagArea/view/tagAreaStyles.js
Normal file
@ -0,0 +1,21 @@
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
textInput: {
|
||||
color: '$white',
|
||||
fontSize: 10,
|
||||
backgroundColor: '#c1c5c7',
|
||||
borderRadius: 50,
|
||||
maxHeight: 18,
|
||||
padding: 5,
|
||||
paddingHorizontal: 10,
|
||||
marginRight: 8,
|
||||
},
|
||||
tagWrapper: {
|
||||
flexDirection: 'row',
|
||||
marginTop: 14,
|
||||
},
|
||||
firstTag: {
|
||||
backgroundColor: '$primaryBlue',
|
||||
},
|
||||
});
|
105
src/components/editorElements/tagArea/view/tagAreaView.js
Normal file
105
src/components/editorElements/tagArea/view/tagAreaView.js
Normal file
@ -0,0 +1,105 @@
|
||||
import React, { Component } from 'react';
|
||||
import { View } from 'react-native';
|
||||
// Constants
|
||||
|
||||
// Components
|
||||
import { Chip } from '../../../basicUIElements';
|
||||
// Styles
|
||||
import styles from './tagAreaStyles';
|
||||
import globalStyles from '../../../../globalStyles';
|
||||
|
||||
export default class TagAreaView extends Component {
|
||||
/* Props
|
||||
* ------------------------------------------------
|
||||
* @prop { type } name - Description....
|
||||
*/
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
currentText: '',
|
||||
chips: [' '],
|
||||
chipsCount: props.chipsCount || 5,
|
||||
};
|
||||
}
|
||||
|
||||
// Component Life Cycles
|
||||
|
||||
// Component Functions
|
||||
_handleOnChange = (text, i) => {
|
||||
this.setState({ currentText: text.trim() });
|
||||
|
||||
if (text.indexOf(' ') > 0 && text) {
|
||||
this._handleTagAdded();
|
||||
}
|
||||
|
||||
if (!text && i !== 0) {
|
||||
this._handleTagRemove(i);
|
||||
}
|
||||
};
|
||||
|
||||
_handleOnBlur = (i) => {
|
||||
this._handleTagAdded(i);
|
||||
};
|
||||
|
||||
_handleTagAdded = (i) => {
|
||||
const { currentText, chips, chipsCount } = this.state;
|
||||
const { handleTagChanged } = this.props;
|
||||
|
||||
if (currentText && currentText.trim() && chips && chips.length < chipsCount) {
|
||||
this.setState({
|
||||
chips: [...chips, currentText.trim()],
|
||||
currentText: '',
|
||||
});
|
||||
}
|
||||
|
||||
if (handleTagChanged && chips.length < chipsCount + 1) {
|
||||
handleTagChanged([...chips, currentText.trim()]);
|
||||
}
|
||||
};
|
||||
|
||||
_handleTagRemove = (i) => {
|
||||
const { chips } = this.state;
|
||||
const { handleTagChanged } = this.props;
|
||||
|
||||
this.setState({
|
||||
chips: chips.filter((_, _i) => _i !== i),
|
||||
});
|
||||
|
||||
if (handleTagChanged) {
|
||||
handleTagChanged(chips.filter((_, _i) => _i !== i));
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { chipsData, isPreviewActive } = this.props;
|
||||
const { chips } = this.state;
|
||||
|
||||
return (
|
||||
<View style={globalStyles.containerHorizontal16}>
|
||||
<View style={styles.tagWrapper}>
|
||||
{chips.map((chip, i) => (
|
||||
<Chip
|
||||
key={i}
|
||||
refs={(input) => {
|
||||
this.inputs[i] = input;
|
||||
}}
|
||||
isPin={i === 0 && chips[1]}
|
||||
placeholderTextColor="#fff"
|
||||
editable={!isPreviewActive}
|
||||
maxLength={50}
|
||||
placeholder="tags"
|
||||
autoFocus={i !== 0 && chips.length - 1 === i}
|
||||
multiline={false}
|
||||
handleOnChange={text => this._handleOnChange(text, i)}
|
||||
handleOnBlur={() => this._handleOnBlur(i)}
|
||||
blurOnSubmit
|
||||
autoCapitalize="none"
|
||||
{...this.props}
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
marginTop: 16,
|
||||
},
|
||||
});
|
25
src/components/editorElements/textArea/view/textAreaView.js
Normal file
25
src/components/editorElements/textArea/view/textAreaView.js
Normal file
@ -0,0 +1,25 @@
|
||||
import React, { Component } from 'react';
|
||||
// Constants
|
||||
|
||||
// Components
|
||||
import { MarkdownEditor } from '../../../markdownEditor';
|
||||
|
||||
export default class TextAreaView extends Component {
|
||||
/* Props
|
||||
* ------------------------------------------------
|
||||
* @prop { type } name - Description....
|
||||
*/
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
// Component Life Cycles
|
||||
|
||||
// Component Functions
|
||||
|
||||
render() {
|
||||
return <MarkdownEditor {...this.props} />;
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
textInput: {
|
||||
color: '$primaryBlack',
|
||||
fontWeight: 'bold',
|
||||
fontSize: 24,
|
||||
},
|
||||
});
|
@ -0,0 +1,57 @@
|
||||
import React, { Component } from 'react';
|
||||
import { TextInput, View } from 'react-native';
|
||||
// Constants
|
||||
|
||||
// Components
|
||||
|
||||
// Styles
|
||||
import styles from './titleAreaStyles';
|
||||
import globalStyles from '../../../../globalStyles';
|
||||
|
||||
export default class TitleAreaView extends Component {
|
||||
/* Props
|
||||
* ------------------------------------------------
|
||||
* @prop { type } name - Description....
|
||||
*/
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
// Component Life Cycles
|
||||
|
||||
// Component Functions
|
||||
_handleOnChange = (text) => {
|
||||
const { onChange, handleIsValid, componentID } = this.props;
|
||||
if (onChange) {
|
||||
onChange(text);
|
||||
}
|
||||
|
||||
if (handleIsValid) {
|
||||
handleIsValid(componentID, !!(text && text.length));
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { value, isPreviewActive } = this.props;
|
||||
|
||||
return (
|
||||
<View style={globalStyles.containerHorizontal16}>
|
||||
<TextInput
|
||||
style={styles.textInput}
|
||||
placeholderTextColor="#c1c5c7"
|
||||
editable={!isPreviewActive}
|
||||
maxLength={250}
|
||||
placeholder="Title"
|
||||
multiline
|
||||
autoFocus
|
||||
numberOfLines={4}
|
||||
onChangeText={text => this._handleOnChange(text)}
|
||||
value={value}
|
||||
{...this.props}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
import React, { Component } from 'react';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
|
||||
// Constants
|
||||
import { default as ROUTES } from '../../../constants/routeNames';
|
||||
|
||||
// Components
|
||||
import { EditorHeaderView } from '..';
|
||||
|
||||
class EditorHeaderContainer extends Component {
|
||||
/* Props
|
||||
* ------------------------------------------------
|
||||
* @prop { funtion } handleOnPressPreviewButton - Preview button active handler....
|
||||
*/
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
// Component Life Cycles
|
||||
|
||||
// Component Functions
|
||||
_handleOnPressBackButton = () => {
|
||||
const { navigation } = this.props;
|
||||
|
||||
navigation.navigate(ROUTES.SCREENS.HOME);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<EditorHeaderView handleOnPressBackButton={this._handleOnPressBackButton} {...this.props} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withNavigation(EditorHeaderContainer);
|
5
src/components/editorHeader/index.js
Normal file
5
src/components/editorHeader/index.js
Normal file
@ -0,0 +1,5 @@
|
||||
import EditorHeaderView from './view/editorHeaderView';
|
||||
import EditorHeader from './container/editorHeaderContainer';
|
||||
|
||||
export { EditorHeaderView, EditorHeader };
|
||||
export default EditorHeader;
|
43
src/components/editorHeader/view/editorHeaderStyles.js
Normal file
43
src/components/editorHeader/view/editorHeaderStyles.js
Normal file
@ -0,0 +1,43 @@
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
container: {
|
||||
// flex: 1,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
padding: 16,
|
||||
width: '$deviceWidth',
|
||||
backgroundColor: '$white',
|
||||
},
|
||||
backIcon: {
|
||||
fontSize: 24,
|
||||
color: '$iconColor',
|
||||
},
|
||||
quickTitle: {
|
||||
flexGrow: 1,
|
||||
fontSize: 10,
|
||||
color: '$iconColor',
|
||||
marginLeft: 24,
|
||||
alignSelf: 'center',
|
||||
},
|
||||
rightIcon: {
|
||||
color: '$iconColor',
|
||||
},
|
||||
iconButton: {
|
||||
marginRight: 24,
|
||||
justifyContent: 'center',
|
||||
alignSelf: 'center',
|
||||
},
|
||||
textButton: {
|
||||
fontSize: 16,
|
||||
},
|
||||
textButtonDisable: {
|
||||
color: '$iconColor',
|
||||
},
|
||||
textButtonEnable: {
|
||||
color: '$primaryBlue',
|
||||
},
|
||||
textButtonWrapper: {
|
||||
justifyContent: 'center',
|
||||
},
|
||||
});
|
82
src/components/editorHeader/view/editorHeaderView.js
Normal file
82
src/components/editorHeader/view/editorHeaderView.js
Normal file
@ -0,0 +1,82 @@
|
||||
import React, { Component } from 'react';
|
||||
import { View, SafeAreaView, Text } from 'react-native';
|
||||
import { TextButton } from '../..';
|
||||
import { IconButton } from '../../iconButton';
|
||||
// Constants
|
||||
|
||||
// Components
|
||||
|
||||
// Styles
|
||||
import styles from './editorHeaderStyles';
|
||||
|
||||
class EditorHeaderView extends Component {
|
||||
/* Props
|
||||
* ------------------------------------------------
|
||||
* @prop { boolean } isFormValid - Righst button propertie
|
||||
* @prop { string } quickTitle - Left side behind back button text
|
||||
*/
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
// Component Life Cycles
|
||||
|
||||
// Component Functions
|
||||
|
||||
_handleOnPress = () => {
|
||||
const { handleOnSubmit } = this.props;
|
||||
|
||||
if (handleOnSubmit) {
|
||||
handleOnSubmit();
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
handleOnPressBackButton,
|
||||
handleOnPressPreviewButton,
|
||||
isPreviewActive,
|
||||
quickTitle,
|
||||
isFormValid,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<View style={styles.container}>
|
||||
<IconButton
|
||||
iconStyle={styles.backIcon}
|
||||
name="md-arrow-back"
|
||||
onPress={() => handleOnPressBackButton()}
|
||||
/>
|
||||
<Text style={styles.quickTitle}>{quickTitle}</Text>
|
||||
<IconButton
|
||||
style={styles.iconButton}
|
||||
iconStyle={styles.rightIcon}
|
||||
size={20}
|
||||
name="ios-timer"
|
||||
/>
|
||||
<IconButton
|
||||
style={styles.iconButton}
|
||||
size={25}
|
||||
onPress={() => handleOnPressPreviewButton()}
|
||||
iconStyle={styles.rightIcon}
|
||||
name={isPreviewActive ? 'ios-eye' : 'ios-eye-off'}
|
||||
/>
|
||||
<TextButton
|
||||
textStyle={[
|
||||
styles.textButton,
|
||||
isFormValid ? styles.textButtonEnable : styles.textButtonDisable,
|
||||
]}
|
||||
onPress={isFormValid && this._handleOnPress}
|
||||
style={styles.textButtonWrapper}
|
||||
text="Publish"
|
||||
/>
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default EditorHeaderView;
|
4
src/components/icon/index.js
Normal file
4
src/components/icon/index.js
Normal file
@ -0,0 +1,4 @@
|
||||
import Icon from './view/iconView';
|
||||
|
||||
export { Icon };
|
||||
export default Icon;
|
0
src/components/icon/view/iconStyles.js
Normal file
0
src/components/icon/view/iconStyles.js
Normal file
60
src/components/icon/view/iconView.js
Normal file
60
src/components/icon/view/iconView.js
Normal file
@ -0,0 +1,60 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Platform } from 'react-native';
|
||||
|
||||
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import SimpleLineIcons from 'react-native-vector-icons/SimpleLineIcons';
|
||||
import FontAwesome from 'react-native-vector-icons/FontAwesome';
|
||||
import Feather from 'react-native-vector-icons/Feather';
|
||||
|
||||
class IconView extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
// for ios its turn ios-eye-off-outline
|
||||
// for android its turn to md-off-outline
|
||||
_getIconName = () => {
|
||||
const { name, androidName } = this.props;
|
||||
|
||||
if (name) {
|
||||
const isIos = Platform.OS === 'ios';
|
||||
let iconName;
|
||||
|
||||
if (!isIos) {
|
||||
iconName = androidName || `md-${name.split('ios-')}`;
|
||||
}
|
||||
return iconName;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
_getIcon = () => {
|
||||
const { iconType } = this.props;
|
||||
const name = this._getIconName();
|
||||
|
||||
switch (iconType) {
|
||||
case 'Feather':
|
||||
return <Feather {...this.props} />;
|
||||
case 'FontAwesome':
|
||||
return <FontAwesome {...this.props} />;
|
||||
case 'SimpleLineIcons':
|
||||
return <SimpleLineIcons {...this.props}>{this.props.children}</SimpleLineIcons>;
|
||||
case 'MaterialCommunityIcons':
|
||||
return (
|
||||
<MaterialCommunityIcons name={name} {...this.props}>
|
||||
{this.props.children}
|
||||
</MaterialCommunityIcons>
|
||||
);
|
||||
default:
|
||||
return <Ionicons {...this.props} />;
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
return this._getIcon();
|
||||
}
|
||||
}
|
||||
|
||||
export default IconView;
|
@ -1,13 +1,12 @@
|
||||
import EStyleSheet from "react-native-extended-stylesheet";
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
iconButton: {
|
||||
width: 30,
|
||||
height: 30,
|
||||
borderRadius: 30 / 2,
|
||||
justifyContent: "center",
|
||||
},
|
||||
icon: {
|
||||
textAlign: "center",
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
icon: {},
|
||||
});
|
||||
|
@ -1,32 +1,43 @@
|
||||
import React from "react";
|
||||
import { View, TouchableHighlight } from "react-native";
|
||||
import Ionicons from "react-native-vector-icons/Ionicons";
|
||||
import React, { Fragment } from 'react';
|
||||
import { TouchableHighlight } from 'react-native';
|
||||
import { Icon } from '../../icon';
|
||||
|
||||
import styles from "./iconButtonStyles";
|
||||
import styles from './iconButtonStyles';
|
||||
|
||||
/* Props
|
||||
* ------------------------------------------------
|
||||
* @prop { type } name - Description....
|
||||
*/
|
||||
|
||||
const IconButton = ({ name, color, size, onPress, backgroundColor, style }) => (
|
||||
<View>
|
||||
const IconButton = ({
|
||||
name,
|
||||
color,
|
||||
size,
|
||||
onPress,
|
||||
backgroundColor,
|
||||
style,
|
||||
iconStyle,
|
||||
iconType,
|
||||
}) => (
|
||||
<Fragment>
|
||||
<TouchableHighlight
|
||||
style={[styles.iconButton, style && style]}
|
||||
style={[!style && styles.iconButton, style && style]}
|
||||
onPress={() => onPress && onPress()}
|
||||
underlayColor={backgroundColor}
|
||||
underlayColor={backgroundColor || 'white'}
|
||||
>
|
||||
<Ionicons
|
||||
<Icon
|
||||
style={[
|
||||
color && { color },
|
||||
backgroundColor && { backgroundColor },
|
||||
styles.icon,
|
||||
color && { color: color },
|
||||
backgroundColor && { backgroundColor: backgroundColor },
|
||||
iconStyle && iconStyle,
|
||||
]}
|
||||
name={name}
|
||||
size={size}
|
||||
iconType={iconType}
|
||||
/>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
</Fragment>
|
||||
);
|
||||
|
||||
export default IconButton;
|
||||
|
4
src/components/markdownEditor/index.js
Normal file
4
src/components/markdownEditor/index.js
Normal file
@ -0,0 +1,4 @@
|
||||
import MarkdownEditor from './view/markdownEditorView';
|
||||
|
||||
export { MarkdownEditor };
|
||||
export default MarkdownEditor;
|
14
src/components/markdownEditor/view/editorBarStyles.js
Normal file
14
src/components/markdownEditor/view/editorBarStyles.js
Normal file
@ -0,0 +1,14 @@
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
container: {
|
||||
flexDirection: 'row',
|
||||
backgroundColor: '$white',
|
||||
alignItems: 'center',
|
||||
height: 48,
|
||||
shadowOpacity: 0.2,
|
||||
shadowOffset: {
|
||||
height: 1.5,
|
||||
},
|
||||
},
|
||||
});
|
@ -0,0 +1,32 @@
|
||||
import { replaceBetween } from './utils';
|
||||
|
||||
export default ({ getState, item, setState }) => {
|
||||
let { text } = getState();
|
||||
const { selection } = getState();
|
||||
text = text || '';
|
||||
let newText;
|
||||
let newSelection;
|
||||
if (selection.start !== selection.end) {
|
||||
newText = replaceBetween(
|
||||
text,
|
||||
selection,
|
||||
`${item.prefix} ${text.substring(selection.start, selection.end)}\n`,
|
||||
);
|
||||
newSelection = { start: selection.end + 3, end: selection.end + 3 };
|
||||
} else if (
|
||||
selection.start === selection.end
|
||||
&& text.substring(selection.end - 1, selection.end) === '\n'
|
||||
) {
|
||||
newText = replaceBetween(text, selection, `${item.prefix} `);
|
||||
newSelection = { start: selection.start + 2, end: selection.start + 2 };
|
||||
} else {
|
||||
newText = replaceBetween(text, selection, `\n${item.prefix} `);
|
||||
newSelection = { start: selection.start + 3, end: selection.start + 3 };
|
||||
}
|
||||
|
||||
setState({ text: newText }, () => {
|
||||
setTimeout(() => {
|
||||
setState({ selection: newSelection });
|
||||
}, 300);
|
||||
});
|
||||
};
|
@ -0,0 +1,35 @@
|
||||
import { isStringWebLink, replaceBetween } from './utils';
|
||||
|
||||
export const writeUrlTextHere = 'https://example.com';
|
||||
export const writeTextHereString = 'Text here!';
|
||||
|
||||
export default ({ getState, item, setState }) => {
|
||||
const { selection, text } = getState();
|
||||
let newText;
|
||||
let newSelection;
|
||||
const selectedText = text.substring(selection.start, selection.end);
|
||||
if (selection.start !== selection.end) {
|
||||
if (isStringWebLink(selectedText)) {
|
||||
newText = replaceBetween(text, selection, `[${writeTextHereString}](${selectedText})`);
|
||||
newSelection = {
|
||||
start: selection.start + 1,
|
||||
end: selection.start + 1 + writeTextHereString.length,
|
||||
};
|
||||
} else {
|
||||
newText = replaceBetween(text, selection, `[${selectedText}](${writeUrlTextHere})`);
|
||||
newSelection = {
|
||||
start: selection.end + 3,
|
||||
end: selection.end + 3 + writeUrlTextHere.length,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
newText = replaceBetween(text, selection, `[${writeTextHereString}](${writeUrlTextHere})`);
|
||||
newSelection = {
|
||||
start: selection.start + 1,
|
||||
end: selection.start + 1 + writeTextHereString.length,
|
||||
};
|
||||
}
|
||||
setState({ text: newText }, () => {
|
||||
setState({ selection: newSelection });
|
||||
});
|
||||
};
|
@ -0,0 +1,27 @@
|
||||
import { replaceBetween } from './utils';
|
||||
|
||||
export default ({ getState, item, setState }) => {
|
||||
const { text, selection } = getState();
|
||||
const newText = replaceBetween(
|
||||
text,
|
||||
selection,
|
||||
item.wrapper.concat(text.substring(selection.start, selection.end), item.wrapper),
|
||||
);
|
||||
let newPosition;
|
||||
if (selection.start === selection.end) {
|
||||
newPosition = selection.end + item.wrapper.length;
|
||||
} else {
|
||||
newPosition = selection.end + item.wrapper.length * 2;
|
||||
}
|
||||
const extra = {
|
||||
selection: {
|
||||
start: newPosition,
|
||||
end: newPosition,
|
||||
},
|
||||
};
|
||||
setState({ text: newText }, () => {
|
||||
setTimeout(() => {
|
||||
setState({ ...extra });
|
||||
}, 25);
|
||||
});
|
||||
};
|
@ -0,0 +1,55 @@
|
||||
import { replaceBetween } from './utils';
|
||||
|
||||
export default ({ getState, item, setState }) => {
|
||||
const { text, selection } = getState();
|
||||
let newText = replaceBetween(
|
||||
text,
|
||||
selection,
|
||||
`\n${item.wrapper.concat(
|
||||
'\n',
|
||||
text.substring(selection.start, selection.end),
|
||||
'\n',
|
||||
item.wrapper,
|
||||
'\n',
|
||||
)}`,
|
||||
);
|
||||
let newPosition;
|
||||
if (selection.start === selection.end) {
|
||||
newPosition = selection.end + item.wrapper.length + 2; // +2 For two new lines
|
||||
newText = replaceBetween(
|
||||
text,
|
||||
selection,
|
||||
`\n${item.wrapper.concat(
|
||||
'\n',
|
||||
text.substring(selection.start, selection.end),
|
||||
'\n',
|
||||
item.wrapper,
|
||||
'\n',
|
||||
)}`,
|
||||
);
|
||||
} else {
|
||||
newPosition = selection.end + item.wrapper.length * 2 + 3; // +3 For three new lines
|
||||
newText = replaceBetween(
|
||||
text,
|
||||
selection,
|
||||
`${item.wrapper.concat(
|
||||
'\n',
|
||||
text.substring(selection.start, selection.end),
|
||||
'\n',
|
||||
item.wrapper,
|
||||
'\n',
|
||||
)}`,
|
||||
);
|
||||
}
|
||||
const extra = {
|
||||
selection: {
|
||||
start: newPosition,
|
||||
end: newPosition,
|
||||
},
|
||||
};
|
||||
setState({ text: newText }, () => {
|
||||
setTimeout(() => {
|
||||
setState({ ...extra });
|
||||
}, 25);
|
||||
});
|
||||
};
|
116
src/components/markdownEditor/view/formats/formats.js
Normal file
116
src/components/markdownEditor/view/formats/formats.js
Normal file
@ -0,0 +1,116 @@
|
||||
import applyWrapFormat from './applyWrapFormat';
|
||||
import applyWrapFormatNewLines from './applyWrapFormatNewLines';
|
||||
import applyListFormat from './applyListFormat';
|
||||
import applyWebLinkFormat from './applyWebLinkFormat';
|
||||
|
||||
export default [
|
||||
{
|
||||
key: 'B',
|
||||
title: 'B',
|
||||
icon: 'bold',
|
||||
iconType: 'Feather',
|
||||
wrapper: '**',
|
||||
onPress: applyWrapFormat,
|
||||
// style: { fontWeight: 'bold' },
|
||||
},
|
||||
{
|
||||
key: 'H1',
|
||||
title: 'H1',
|
||||
icon: 'format-size',
|
||||
iconType: 'MaterialCommunityIcons',
|
||||
prefix: '#',
|
||||
onPress: applyListFormat,
|
||||
},
|
||||
{
|
||||
key: 'L',
|
||||
title: 'L',
|
||||
icon: 'list',
|
||||
iconType: 'Feather',
|
||||
prefix: '-',
|
||||
onPress: applyListFormat,
|
||||
},
|
||||
{
|
||||
key: 'C',
|
||||
title: 'C',
|
||||
icon: 'ios-code',
|
||||
wrapper: '`',
|
||||
onPress: applyWrapFormat,
|
||||
},
|
||||
{
|
||||
key: 'I',
|
||||
title: 'I',
|
||||
icon: 'italic',
|
||||
iconType: 'Feather',
|
||||
wrapper: '*',
|
||||
onPress: applyWrapFormat,
|
||||
},
|
||||
{
|
||||
key: 'U',
|
||||
title: 'U',
|
||||
icon: 'underline',
|
||||
iconType: 'Feather',
|
||||
wrapper: '__',
|
||||
onPress: applyWrapFormat,
|
||||
},
|
||||
{
|
||||
key: 'S',
|
||||
title: 'S',
|
||||
wrapper: '~~',
|
||||
icon: 'strikethrough',
|
||||
iconType: 'FontAwesome',
|
||||
onPress: applyWrapFormat,
|
||||
},
|
||||
{
|
||||
key: '>',
|
||||
title: '>',
|
||||
prefix: '>',
|
||||
icon: 'ios-quote',
|
||||
onPress: applyListFormat,
|
||||
},
|
||||
|
||||
{
|
||||
key: 'CC',
|
||||
title: 'CC',
|
||||
icon: 'ios-code-working',
|
||||
wrapper: '```',
|
||||
onPress: applyWrapFormatNewLines,
|
||||
},
|
||||
|
||||
{
|
||||
key: 'WEB',
|
||||
title: 'WEB',
|
||||
icon: 'link-2',
|
||||
iconType: 'Feather',
|
||||
onPress: applyWebLinkFormat,
|
||||
},
|
||||
// {
|
||||
// key: 'H2',
|
||||
// title: 'H2',
|
||||
// prefix: '##',
|
||||
// onPress: applyListFormat,
|
||||
// },
|
||||
// {
|
||||
// key: 'H3',
|
||||
// title: 'H3',
|
||||
// prefix: '###',
|
||||
// onPress: applyListFormat,
|
||||
// },
|
||||
// {
|
||||
// key: 'H4',
|
||||
// title: 'H4',
|
||||
// prefix: '####',
|
||||
// onPress: applyListFormat,
|
||||
// },
|
||||
// {
|
||||
// key: 'H5',
|
||||
// title: 'H5',
|
||||
// prefix: '#####',
|
||||
// onPress: applyListFormat,
|
||||
// },
|
||||
// {
|
||||
// key: 'H6',
|
||||
// title: 'H6',
|
||||
// prefix: '######',
|
||||
// onPress: applyListFormat,
|
||||
// },
|
||||
];
|
8
src/components/markdownEditor/view/formats/utils.js
Normal file
8
src/components/markdownEditor/view/formats/utils.js
Normal file
@ -0,0 +1,8 @@
|
||||
import regexValidator from './webLinkValidator';
|
||||
|
||||
export const replaceBetween = (text: string, selection: Object, what: string) => text.substring(0, selection.start) + what + text.substring(selection.end);
|
||||
|
||||
export const isStringWebLink = (text: string): boolean => {
|
||||
const pattern = regexValidator;
|
||||
return pattern.test(text);
|
||||
};
|
@ -0,0 +1,45 @@
|
||||
// Regular Expression for URL validation
|
||||
//
|
||||
// Author: Diego Perini
|
||||
// Updated: 2010/12/05
|
||||
// License: MIT
|
||||
//
|
||||
// Copyright (c) 2010-2013 Diego Perini (http://www.iport.it)
|
||||
//
|
||||
export default new RegExp(
|
||||
'^'
|
||||
// protocol identifier
|
||||
+ '(?:(?:https?|ftp)://)'
|
||||
// user:pass authentication
|
||||
+ '(?:\\S+(?::\\S*)?@)?'
|
||||
+ '(?:'
|
||||
// IP address exclusion
|
||||
// private & local networks
|
||||
+ '(?!(?:10|127)(?:\\.\\d{1,3}){3})'
|
||||
+ '(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})'
|
||||
+ '(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})'
|
||||
// IP address dotted notation octets
|
||||
// excludes loopback network 0.0.0.0
|
||||
// excludes reserved space >= 224.0.0.0
|
||||
// excludes network & broacast addresses
|
||||
// (first & last IP address of each class)
|
||||
+ '(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])'
|
||||
+ '(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}'
|
||||
+ '(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))'
|
||||
+ '|'
|
||||
// host name
|
||||
+ '(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)'
|
||||
// domain name
|
||||
+ '(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*'
|
||||
// TLD identifier
|
||||
+ '(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))'
|
||||
// TLD may end with dot
|
||||
+ '\\.?'
|
||||
+ ')'
|
||||
// port number
|
||||
+ '(?::\\d{2,5})?'
|
||||
// resource path
|
||||
+ '(?:[/?#]\\S*)?'
|
||||
+ '$',
|
||||
'i',
|
||||
);
|
56
src/components/markdownEditor/view/markdownEditorStyles.js
Normal file
56
src/components/markdownEditor/view/markdownEditorStyles.js
Normal file
@ -0,0 +1,56 @@
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
alignItems: 'stretch',
|
||||
backgroundColor: '$white',
|
||||
},
|
||||
textWrapper: {
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
fontSize: 12,
|
||||
marginVertical: 16,
|
||||
paddingHorizontal: 16,
|
||||
},
|
||||
inlinePadding: {
|
||||
padding: 8,
|
||||
},
|
||||
editorButtons: {
|
||||
flexDirection: 'row',
|
||||
backgroundColor: '$white',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
height: 50,
|
||||
shadowOpacity: 0.2,
|
||||
shadowOffset: {
|
||||
height: 1.5,
|
||||
},
|
||||
},
|
||||
leftButtonsWrapper: {
|
||||
marginLeft: 16,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
maxWidth: '$deviceWidth / 1.85',
|
||||
},
|
||||
rightButtonsWrapper: {
|
||||
marginRight: 16,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
},
|
||||
editorButton: {
|
||||
color: '$primaryDarkGray',
|
||||
paddingRight: 22,
|
||||
height: 24,
|
||||
},
|
||||
dropdownStyle: {
|
||||
marginRight: 8,
|
||||
},
|
||||
rightIcons: {
|
||||
paddingRight: 21,
|
||||
},
|
||||
dropdownIconStyle: {
|
||||
color: '$primaryDarkGray',
|
||||
},
|
||||
});
|
152
src/components/markdownEditor/view/markdownEditorView.js
Normal file
152
src/components/markdownEditor/view/markdownEditorView.js
Normal file
@ -0,0 +1,152 @@
|
||||
import React, { Component } from 'react';
|
||||
import {
|
||||
View, TextInput, KeyboardAvoidingView, ScrollView, FlatList,
|
||||
} from 'react-native';
|
||||
import { MarkdownView } from 'react-native-markdown-view';
|
||||
|
||||
// Components
|
||||
import Formats from './formats/formats';
|
||||
import { IconButton } from '../../iconButton';
|
||||
import { DropdownButton } from '../../dropdownButton';
|
||||
|
||||
// Styles
|
||||
import styles from './markdownEditorStyles';
|
||||
import previewStyles from './markdownPreviewStyles';
|
||||
|
||||
export default class MarkdownEditorView extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
text: '',
|
||||
selection: { start: 0, end: 0 },
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.textInput.focus();
|
||||
}
|
||||
|
||||
changeText = (input) => {
|
||||
const {
|
||||
onChange, handleOnTextChange, handleIsValid, componentID,
|
||||
} = this.props;
|
||||
|
||||
this.setState({ text: input });
|
||||
|
||||
if (onChange) {
|
||||
onChange(input);
|
||||
}
|
||||
|
||||
if (handleIsValid) {
|
||||
handleIsValid(componentID, !!(input && input.length));
|
||||
}
|
||||
|
||||
handleOnTextChange && handleOnTextChange(input);
|
||||
};
|
||||
|
||||
_handleOnSelectionChange = (event) => {
|
||||
this.setState({
|
||||
selection: event.nativeEvent.selection,
|
||||
});
|
||||
};
|
||||
|
||||
_getState = () => {
|
||||
this.setState({
|
||||
selection: {
|
||||
start: 1,
|
||||
end: 1,
|
||||
},
|
||||
});
|
||||
return this.state;
|
||||
};
|
||||
|
||||
_renderPreview = () => {
|
||||
const { text } = this.state;
|
||||
|
||||
return (
|
||||
<View style={styles.textWrapper}>
|
||||
<ScrollView removeClippedSubviews>
|
||||
<MarkdownView styles={previewStyles}>{text === '' ? '...' : text}</MarkdownView>
|
||||
</ScrollView>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
_renderMarkupButton = ({ item, getState, setState }) => (
|
||||
<View style={styles.buttonWrapper}>
|
||||
<IconButton
|
||||
size={20}
|
||||
style={styles.editorButton}
|
||||
iconType={item.iconType}
|
||||
name={item.icon}
|
||||
onPress={() => item.onPress({ getState, setState, item })}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
|
||||
_renderEditorButtons = ({ getState, setState }) => (
|
||||
<View style={styles.editorButtons}>
|
||||
<View style={styles.leftButtonsWrapper}>
|
||||
<FlatList
|
||||
data={Formats}
|
||||
keyboardShouldPersistTaps="always"
|
||||
renderItem={({ item }) => this._renderMarkupButton({ item, getState, setState })}
|
||||
horizontal
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.rightButtonsWrapper}>
|
||||
<IconButton
|
||||
size={20}
|
||||
style={styles.rightIcons}
|
||||
iconType="Feather"
|
||||
name="link-2"
|
||||
onPress={() => Formats[9].onPress({ getState, setState })}
|
||||
/>
|
||||
<IconButton style={styles.rightIcons} size={20} iconType="Feather" name="image" />
|
||||
<DropdownButton
|
||||
style={styles.dropdownStyle}
|
||||
options={['option1', 'option2', 'option3', 'option4']}
|
||||
iconName="md-more"
|
||||
iconStyle={styles.dropdownIconStyle}
|
||||
isHasChildIcon
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
|
||||
render() {
|
||||
const { isPreviewActive } = this.props;
|
||||
const { text, selection } = this.state;
|
||||
|
||||
return (
|
||||
<KeyboardAvoidingView style={styles.container} behavior="padding">
|
||||
{!isPreviewActive ? (
|
||||
<TextInput
|
||||
multiline
|
||||
onChangeText={text => this.changeText(text)}
|
||||
onSelectionChange={this._handleOnSelectionChange}
|
||||
placeholder="What would you like to write about today?"
|
||||
placeholderTextColor="#c1c5c7"
|
||||
ref={textInput => (this.textInput = textInput)}
|
||||
selection={selection}
|
||||
selectionColor="#357ce6"
|
||||
style={styles.textWrapper}
|
||||
underlineColorAndroid="transparent"
|
||||
value={text}
|
||||
{...this.props}
|
||||
/>
|
||||
) : (
|
||||
this._renderPreview()
|
||||
)}
|
||||
{!isPreviewActive
|
||||
&& this._renderEditorButtons({
|
||||
getState: this._getState,
|
||||
setState: (state, callback) => {
|
||||
this.textInput.focus();
|
||||
this.setState(state, callback);
|
||||
},
|
||||
})}
|
||||
</KeyboardAvoidingView>
|
||||
);
|
||||
}
|
||||
}
|
16
src/components/markdownEditor/view/markdownPreviewStyles.js
Normal file
16
src/components/markdownEditor/view/markdownPreviewStyles.js
Normal file
@ -0,0 +1,16 @@
|
||||
export const markdownPreviewStyles = {
|
||||
heading1: {
|
||||
fontSize: 24,
|
||||
color: 'red',
|
||||
backgroundColor: 'red',
|
||||
},
|
||||
link: {
|
||||
color: 'pink',
|
||||
},
|
||||
mailTo: {
|
||||
color: 'orange',
|
||||
},
|
||||
text: {
|
||||
color: '#555555',
|
||||
},
|
||||
};
|
31
src/components/markdownEditor/view/renderButtons.js
Normal file
31
src/components/markdownEditor/view/renderButtons.js
Normal file
@ -0,0 +1,31 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
FlatList, TouchableOpacity, Text, View,
|
||||
} from 'react-native';
|
||||
|
||||
import Formats from './formats/formats';
|
||||
|
||||
import styles from './editorBarStyles';
|
||||
|
||||
const FOREGROUND_COLOR = '#788187';
|
||||
const defaultStyles = { padding: 8, color: FOREGROUND_COLOR, fontSize: 16 };
|
||||
|
||||
const defaultMarkdownButton = ({ item, getState, setState }) => (
|
||||
<TouchableOpacity onPress={() => item.onPress({ getState, setState, item })}>
|
||||
<Text style={[defaultStyles, item.style]}>{item.title}</Text>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
|
||||
export const renderEditorButtons = ({ getState, setState }, formats, markdownButton) => (
|
||||
<View style={styles.container}>
|
||||
<FlatList
|
||||
data={formats || Formats}
|
||||
keyboardShouldPersistTaps="always"
|
||||
renderItem={({ item, index }) => (markdownButton
|
||||
? markdownButton({ item, getState, setState })
|
||||
: defaultMarkdownButton({ item, getState, setState }))
|
||||
}
|
||||
horizontal
|
||||
/>
|
||||
</View>
|
||||
);
|
@ -1,15 +1,13 @@
|
||||
import React, { Fragment, Component } from "react";
|
||||
import { View } from "react-native";
|
||||
import React, { Component } from 'react';
|
||||
import { View } from 'react-native';
|
||||
|
||||
import { CircularButton, IconButton } from "../../";
|
||||
import { CircularButton, IconButton } from '../..';
|
||||
|
||||
import styles from "./numericKeyboardStyles";
|
||||
import styles from './numericKeyboardStyles';
|
||||
|
||||
class NumericKeyboard extends Component {
|
||||
/* Props
|
||||
*
|
||||
* @prop { func } onPress - Function will trigger when any button clicked.
|
||||
*
|
||||
*/
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@ -20,7 +18,7 @@ class NumericKeyboard extends Component {
|
||||
|
||||
// Component Functions
|
||||
|
||||
_handleOnPress = value => {
|
||||
_handleOnPress = (value) => {
|
||||
alert(value);
|
||||
};
|
||||
|
||||
@ -98,7 +96,7 @@ class NumericKeyboard extends Component {
|
||||
/>
|
||||
|
||||
<IconButton
|
||||
handleOnPress={() => onPress && onPress("clear")}
|
||||
handleOnPress={() => onPress && onPress('clear')}
|
||||
isCircle
|
||||
style={styles.iconButton}
|
||||
name="close"
|
||||
|
28
src/components/postButton/container/postButtonContainer.js
Normal file
28
src/components/postButton/container/postButtonContainer.js
Normal file
@ -0,0 +1,28 @@
|
||||
import React, { Component } from 'react';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
|
||||
// Components
|
||||
import { PostButtonView } from '..';
|
||||
|
||||
class PostButtonContainer extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
// Component Life Cycle Functions
|
||||
|
||||
// Component Functions
|
||||
|
||||
_handleSubButtonPress = (route) => {
|
||||
const { navigation } = this.props;
|
||||
|
||||
navigation.navigate(route);
|
||||
};
|
||||
|
||||
render() {
|
||||
return <PostButtonView handleSubButtonPress={this._handleSubButtonPress} {...this.props} />;
|
||||
}
|
||||
}
|
||||
|
||||
export default withNavigation(PostButtonContainer);
|
@ -1,4 +1,5 @@
|
||||
import PostButton from './view/postButtonView';
|
||||
import PostButtonView from './view/postButtonView';
|
||||
import PostButton from './container/postButtonContainer';
|
||||
|
||||
export { PostButton };
|
||||
export { PostButtonView, PostButton };
|
||||
export default PostButton;
|
||||
|
@ -81,15 +81,7 @@ class PostButtonView extends Component {
|
||||
outputRange: ['0deg', '45deg'],
|
||||
});
|
||||
|
||||
// const bluring = this.mode.interpolate({
|
||||
// inputRange: [0, 1],
|
||||
// outputRange: [10, 5],
|
||||
// });
|
||||
|
||||
// const blurin2 = this.mode.interpolate({
|
||||
// inputRange: [0, 1],
|
||||
// outputRange: [0, -20],
|
||||
// });
|
||||
const { handleSubButtonPress } = this.props;
|
||||
|
||||
return (
|
||||
<View style={styles.postButtonWrapper}>
|
||||
@ -108,6 +100,7 @@ class PostButtonView extends Component {
|
||||
top: secondY,
|
||||
}}
|
||||
icon="pencil"
|
||||
onPress={() => handleSubButtonPress('EditorScreen')}
|
||||
/>
|
||||
<SubPostButton
|
||||
size={SIZE}
|
||||
|
4
src/components/postForm/index.js
Normal file
4
src/components/postForm/index.js
Normal file
@ -0,0 +1,4 @@
|
||||
import PostForm from './view/postFormView';
|
||||
|
||||
export { PostForm };
|
||||
export default PostForm;
|
46
src/components/postForm/view/postFormView.js
Normal file
46
src/components/postForm/view/postFormView.js
Normal file
@ -0,0 +1,46 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
|
||||
class PostFormView extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
_handleOnSubmitEditing = (returnKeyType = null, inputElement = null) => {
|
||||
const { handleOnSubmit, isFormValid } = this.props;
|
||||
|
||||
if (isFormValid && handleOnSubmit && returnKeyType === 'done') {
|
||||
handleOnSubmit();
|
||||
} else if (returnKeyType === 'next' && inputElement) {
|
||||
// TODO: its accept current input but its should be next input ref
|
||||
inputElement.focus();
|
||||
}
|
||||
};
|
||||
|
||||
_handleOnChange = (componentID, value, isValid = null) => {
|
||||
const { handleFormUpdate } = this.props;
|
||||
|
||||
handleFormUpdate(componentID, value, !!isValid || !!value);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { children, isFormValid, isPreviewActive } = this.props;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{React.Children.map(children, (child) => {
|
||||
if (child) {
|
||||
return React.cloneElement(child, {
|
||||
onSubmitEditing: item => this._handleOnSubmitEditing(child.props.returnKeyType, item),
|
||||
onChange: value => this._handleOnChange(child.props.componentID, value),
|
||||
returnKeyType: isFormValid ? 'done' : 'next',
|
||||
isPreviewActive,
|
||||
});
|
||||
}
|
||||
})}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default PostFormView;
|
@ -29,7 +29,7 @@ class SideMenuContainer extends Component {
|
||||
|
||||
// Component Functions
|
||||
|
||||
_navigateToRoute = (route) => {
|
||||
_navigateToRoute = (route = null) => {
|
||||
const { navigation } = this.props;
|
||||
navigation.navigate(route);
|
||||
};
|
||||
|
@ -28,6 +28,7 @@ class SideMenuView extends Component {
|
||||
|
||||
render() {
|
||||
const { isLoggedIn, userAvatar, navigateToRoute } = this.props;
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View style={styles.headerView}>
|
||||
|
@ -3,7 +3,9 @@ import { BaseNavigator } from '../navigation';
|
||||
import { default as ROUTES } from '../constants/routeNames';
|
||||
|
||||
// Screens
|
||||
import { Splash, Login, PinCode } from '../screens';
|
||||
import {
|
||||
Editor, Login, PinCode, Splash,
|
||||
} from '../screens';
|
||||
|
||||
// Components
|
||||
import { SideMenu } from '../components';
|
||||
@ -23,8 +25,9 @@ const mainNavigation = DrawerNavigator(
|
||||
);
|
||||
|
||||
export default SwitchNavigator({
|
||||
[ROUTES.SCREENS.SPLASH]: { screen: Splash },
|
||||
[ROUTES.DRAWER.MAIN]: mainNavigation,
|
||||
[ROUTES.SCREENS.EDITOR]: { screen: Editor },
|
||||
[ROUTES.SCREENS.LOGIN]: { screen: Login },
|
||||
[ROUTES.SCREENS.PINCODE]: { screen: PinCode },
|
||||
[ROUTES.DRAWER.MAIN]: mainNavigation,
|
||||
[ROUTES.SCREENS.SPLASH]: { screen: Splash },
|
||||
});
|
||||
|
@ -3,10 +3,11 @@ const DRAWER_SUFFIX = 'Drawer';
|
||||
|
||||
export default {
|
||||
SCREENS: {
|
||||
SPLASH: `Splash${SCREEN_SUFFIX}`,
|
||||
EDITOR: `Editor${SCREEN_SUFFIX}`,
|
||||
HOME: `Home${SCREEN_SUFFIX}`,
|
||||
LOGIN: `Login${SCREEN_SUFFIX}`,
|
||||
PINCODE: `PinCode${SCREEN_SUFFIX}`,
|
||||
HOME: `Home${SCREEN_SUFFIX}`,
|
||||
SPLASH: `Splash${SCREEN_SUFFIX}`,
|
||||
},
|
||||
DRAWER: {
|
||||
MAIN: `Main${DRAWER_SUFFIX}`,
|
||||
|
@ -1,10 +1,11 @@
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
container: {
|
||||
containerHorizontal16: {
|
||||
paddingHorizontal: 16,
|
||||
},
|
||||
defaultContainer: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
title: {},
|
||||
text: {
|
||||
|
76
src/screens/editor/container/editorContainer.js
Normal file
76
src/screens/editor/container/editorContainer.js
Normal file
@ -0,0 +1,76 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
// Services and Actions
|
||||
import { postContent } from '../../../providers/steem/dsteem';
|
||||
import { getUserData } from '../../../realm/realm';
|
||||
|
||||
// Middleware
|
||||
|
||||
// Constants
|
||||
import { default as ROUTES } from '../../../constants/routeNames';
|
||||
|
||||
// Utilities
|
||||
import { generatePermlink } from '../../../utils/editor';
|
||||
import { decryptKey } from '../../../utils/crypto';
|
||||
|
||||
// Component
|
||||
import { EditorScreen } from '../screen/editorScreen';
|
||||
|
||||
/*
|
||||
* Props Name Description Value
|
||||
*@props --> props name here description here Value Type Here
|
||||
*
|
||||
*/
|
||||
|
||||
class ExampleContainer extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
// Component Life Cycle Functions
|
||||
|
||||
// Component Functions
|
||||
|
||||
_submitPost = async (form) => {
|
||||
const { navigation } = this.props;
|
||||
let userData;
|
||||
let postingKey;
|
||||
const title = form.formFields['title-area'].content;
|
||||
const permlink = generatePermlink(title);
|
||||
|
||||
await getUserData().then((res) => {
|
||||
userData = res && Array.from(res)[0];
|
||||
postingKey = decryptKey(userData.postingKey, '1234');
|
||||
});
|
||||
|
||||
if (userData) {
|
||||
const post = {
|
||||
body: form.formFields['text-area'].content,
|
||||
title,
|
||||
author: userData.username,
|
||||
permlink: permlink && permlink,
|
||||
tags: form.tags,
|
||||
};
|
||||
|
||||
postContent(post, postingKey)
|
||||
.then((result) => {
|
||||
alert('Your post succesfully shared');
|
||||
navigation.navigate(ROUTES.SCREENS.HOME);
|
||||
})
|
||||
.catch((error) => {
|
||||
alert(`Opps! there is a problem${error}`);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
_handleSubmit = (form) => {
|
||||
this._submitPost(form);
|
||||
};
|
||||
|
||||
render() {
|
||||
return <EditorScreen handleOnSubmit={this._handleSubmit} />;
|
||||
}
|
||||
}
|
||||
|
||||
export default ExampleContainer;
|
@ -1,188 +0,0 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
Container,
|
||||
Header,
|
||||
Left,
|
||||
Body,
|
||||
Right,
|
||||
Button,
|
||||
Icon,
|
||||
Title,
|
||||
Content,
|
||||
} from 'native-base';
|
||||
import { MarkdownEditor } from 'react-native-markdown-editor';
|
||||
import {
|
||||
StatusBar,
|
||||
View,
|
||||
TextInput,
|
||||
TouchableOpacity,
|
||||
Text,
|
||||
} from 'react-native';
|
||||
import Tags from '@esteemapp/react-native-tags';
|
||||
import { postContent } from '../../providers/steem/dsteem';
|
||||
import { getUserData, getAuthStatus } from '../../realm/realm';
|
||||
import { decryptKey } from '../../utils/crypto';
|
||||
|
||||
class EditorPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onChangeBody = this.onChangeBody.bind(this);
|
||||
this.onChangeTitle = this.onChangeTitle.bind(this);
|
||||
this.onChangeTags = this.onChangeTags.bind(this);
|
||||
|
||||
this.state = {
|
||||
body: '',
|
||||
title: '',
|
||||
author: '',
|
||||
permlink: '',
|
||||
tags: ['esteem'],
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {}
|
||||
|
||||
onChangeBody = (body) => {
|
||||
this.setState({
|
||||
body,
|
||||
});
|
||||
};
|
||||
|
||||
onChangeTitle = (title) => {
|
||||
this.setState({
|
||||
title,
|
||||
});
|
||||
};
|
||||
|
||||
onChangeTags = (tags) => {
|
||||
this.setState({
|
||||
tags,
|
||||
});
|
||||
};
|
||||
|
||||
generatePermlink = () => {
|
||||
let title;
|
||||
|
||||
title = this.state.title
|
||||
.replace(/[^\w\s]/gi, '')
|
||||
.replace(/\s\s+/g, '-')
|
||||
.replace(/\s/g, '-')
|
||||
.toLowerCase();
|
||||
title = `${title
|
||||
}-id-${
|
||||
Math.random()
|
||||
.toString(36)
|
||||
.substr(2, 16)}`;
|
||||
|
||||
return title;
|
||||
};
|
||||
|
||||
submitPost = async () => {
|
||||
let userData;
|
||||
let postingKey;
|
||||
|
||||
await getUserData().then((res) => {
|
||||
userData = Array.from(res);
|
||||
postingKey = decryptKey(userData[0].postingKey, 'pinCode');
|
||||
});
|
||||
|
||||
post = {
|
||||
body: this.state.body,
|
||||
title: this.state.title,
|
||||
author: userData[0].username,
|
||||
permlink: this.generatePermlink(),
|
||||
tags: this.state.tags,
|
||||
};
|
||||
|
||||
console.log(post);
|
||||
|
||||
postContent(post, postingKey)
|
||||
.then((result) => {
|
||||
console.log(result);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Container style={{ flex: 1 }}>
|
||||
<View style={{ flex: 1, flexDirection: 'column' }}>
|
||||
<TextInput
|
||||
placeholder="Title"
|
||||
onChangeText={title => this.onChangeTitle(title)}
|
||||
style={{
|
||||
borderWidth: 1,
|
||||
borderColor: 'lightgray',
|
||||
height: 40,
|
||||
margin: 10,
|
||||
borderRadius: 10,
|
||||
flex: 0.08,
|
||||
}}
|
||||
/>
|
||||
<Tags
|
||||
initialText=""
|
||||
initialTags={this.state.tags}
|
||||
onChangeTags={tags => this.onChangeTags(tags)}
|
||||
onTagLongPress={(index, tagLabel, event, deleted) => console.log(
|
||||
index,
|
||||
tagLabel,
|
||||
event,
|
||||
deleted ? 'deleted' : 'not deleted',
|
||||
)
|
||||
}
|
||||
containerStyle={{ justifyContent: 'center' }}
|
||||
inputStyle={{ backgroundColor: 'white' }}
|
||||
maxNumberOfTags={5}
|
||||
tagContainerStyle={{
|
||||
height: 25,
|
||||
backgroundColor: '#284b78',
|
||||
}}
|
||||
tagTextStyle={{ fontWeight: '600', color: 'white' }}
|
||||
style={{
|
||||
borderWidth: 1,
|
||||
borderColor: 'lightgray',
|
||||
flex: 0.12,
|
||||
}}
|
||||
/>
|
||||
<View style={{ borderRadius: 10, flex: 0.7 }}>
|
||||
<MarkdownEditor
|
||||
onMarkdownChange={(text) => {
|
||||
this.onChangeBody(text);
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View style={{ flex: 0.1, flexDirection: 'row' }}>
|
||||
<View style={{ flex: 0.7 }}>
|
||||
<Text>Options</Text>
|
||||
</View>
|
||||
<View style={{ flex: 0.3 }}>
|
||||
<TouchableOpacity
|
||||
onPress={this.submitPost}
|
||||
style={{
|
||||
borderRadius: 10,
|
||||
backgroundColor: '#284b78',
|
||||
width: 100,
|
||||
height: 20,
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
color: 'white',
|
||||
alignSelf: 'center',
|
||||
}}
|
||||
>
|
||||
Submit
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default EditorPage;
|
4
src/screens/editor/index.js
Normal file
4
src/screens/editor/index.js
Normal file
@ -0,0 +1,4 @@
|
||||
import Editor from './container/editorContainer';
|
||||
|
||||
export { Editor };
|
||||
export default Editor;
|
117
src/screens/editor/screen/editorScreen.js
Normal file
117
src/screens/editor/screen/editorScreen.js
Normal file
@ -0,0 +1,117 @@
|
||||
import React, { Component } from 'react';
|
||||
import { View } from 'react-native';
|
||||
|
||||
// Utils
|
||||
import { getWordsCount } from '../../../utils/editor';
|
||||
|
||||
// Constants
|
||||
|
||||
// Components
|
||||
import { EditorHeader } from '../../../components/editorHeader';
|
||||
import { TitleArea, TagArea, TextArea } from '../../../components/editorElements';
|
||||
import { PostForm } from '../../../components/postForm';
|
||||
// Styles
|
||||
import globalStyles from '../../../globalStyles';
|
||||
|
||||
export class EditorScreen extends Component {
|
||||
/* Props
|
||||
* ------------------------------------------------
|
||||
* @prop { type } name - Description....
|
||||
*/
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isPreviewActive: false,
|
||||
wordsCount: null,
|
||||
formFields: {},
|
||||
isFormValid: false,
|
||||
tags: [],
|
||||
};
|
||||
}
|
||||
|
||||
// Component Life Cycles
|
||||
|
||||
// Component Functions
|
||||
_handleOnPressPreviewButton = () => {
|
||||
const { isPreviewActive } = this.state;
|
||||
|
||||
this.setState({ isPreviewActive: !isPreviewActive });
|
||||
};
|
||||
|
||||
_setWordsCount = (content) => {
|
||||
const _wordsCount = getWordsCount(content);
|
||||
const { wordsCount } = this.state;
|
||||
|
||||
if (_wordsCount !== wordsCount) {
|
||||
this.setState({ wordsCount: _wordsCount });
|
||||
}
|
||||
};
|
||||
|
||||
_handleOnSubmit = () => {
|
||||
const { handleOnSubmit } = this.props;
|
||||
const { formFields, tags } = this.state;
|
||||
|
||||
if (handleOnSubmit) {
|
||||
handleOnSubmit({ formFields, tags });
|
||||
}
|
||||
};
|
||||
|
||||
_handleIsFormValid = () => {
|
||||
const { formFields, tags } = this.state;
|
||||
|
||||
this.setState({
|
||||
isFormValid:
|
||||
formFields['title-area']
|
||||
&& formFields['text-area']
|
||||
&& formFields['title-area'].isValid
|
||||
&& formFields['text-area'].isValid
|
||||
&& tags
|
||||
&& tags.length > 0,
|
||||
});
|
||||
};
|
||||
|
||||
_handleFormUpdate = (componentID, content, isValid) => {
|
||||
const { formFields } = this.state;
|
||||
const newFormFields = formFields;
|
||||
|
||||
newFormFields[componentID] = {
|
||||
content,
|
||||
isValid,
|
||||
};
|
||||
|
||||
this.setState({ formFields: newFormFields });
|
||||
|
||||
this._handleIsFormValid();
|
||||
};
|
||||
|
||||
_handleOnTagAdded = (tags) => {
|
||||
this.setState({ tags: tags.filter(tag => tag && tag !== ' ') });
|
||||
};
|
||||
|
||||
render() {
|
||||
const { isPreviewActive, wordsCount, isFormValid } = this.state;
|
||||
|
||||
return (
|
||||
<View style={globalStyles.defaultContainer}>
|
||||
<EditorHeader
|
||||
isPreviewActive={isPreviewActive}
|
||||
quickTitle={wordsCount > 0 && `${wordsCount} words`}
|
||||
handleOnPressPreviewButton={this._handleOnPressPreviewButton}
|
||||
isFormValid={isFormValid}
|
||||
handleOnSubmit={this._handleOnSubmit}
|
||||
/>
|
||||
<PostForm
|
||||
handleFormUpdate={this._handleFormUpdate}
|
||||
handleOnSubmit={this._handleOnSubmit}
|
||||
isPreviewActive={isPreviewActive}
|
||||
isFormValid={isFormValid}
|
||||
>
|
||||
<TitleArea componentID="title-area" />
|
||||
<TagArea componentID="tag-area" handleTagChanged={this._handleOnTagAdded} />
|
||||
<TextArea handleOnTextChange={this._setWordsCount} componentID="text-area" />
|
||||
</PostForm>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,9 +1,10 @@
|
||||
import PinCode from './pinCode';
|
||||
import Splash from './splash';
|
||||
import { Editor } from './editor';
|
||||
import { Home } from './home';
|
||||
import { Login } from './login';
|
||||
import { Profile } from './profile';
|
||||
import { Notification } from './notification';
|
||||
import { Profile } from './profile';
|
||||
|
||||
// import Author from './authorProfile';
|
||||
// import SideMenu from './sideMenuScreen';
|
||||
@ -18,12 +19,13 @@ import { Notification } from './notification';
|
||||
// import { Notification } from './notification';
|
||||
|
||||
export {
|
||||
Editor,
|
||||
Home,
|
||||
Login,
|
||||
PinCode,
|
||||
Splash,
|
||||
Profile,
|
||||
Notification,
|
||||
PinCode,
|
||||
Profile,
|
||||
Splash,
|
||||
// Author,
|
||||
// SideMenu,
|
||||
// Hot,
|
||||
|
15
src/utils/editor.js
Normal file
15
src/utils/editor.js
Normal file
@ -0,0 +1,15 @@
|
||||
export const getWordsCount = text => (text && typeof text === 'string' ? text.replace(/^\s+|\s+$/g, '').split(/\s+/).length : 0);
|
||||
|
||||
export const generatePermlink = (text) => {
|
||||
if (text) {
|
||||
const re = /[^a-z0-9]+/gi;
|
||||
const re2 = /^-*|-*$/g;
|
||||
let permlink = text.replace(re, '-');
|
||||
|
||||
permlink = `${permlink.replace(re2, '').toLowerCase()}-id-${Math.random()
|
||||
.toString(36)
|
||||
.substr(2, 16)}`;
|
||||
return permlink;
|
||||
}
|
||||
return null;
|
||||
};
|
Loading…
Reference in New Issue
Block a user