Compare commits

..
47 Commits
Author SHA1 Message Date
Gene S cc99b267bb swapping host name 2016-02-01 09:52:22 -08:00
Gene S cf38f55291 swapping host name 2016-02-01 09:50:18 -08:00
or-else 1483740189 making the app adaptive - now works on mobile 2016-01-31 20:04:37 -08:00
or-else f5e91a6366 update readme 2016-01-29 20:44:42 -08:00
or-else 0e539c0a98 change host from local to remote 2016-01-29 20:16:17 -08:00
Gene S d1265c21ee adding avatar support 2016-01-29 19:23:02 -08:00
Gene S 9a855a7288 removing unused icons 2016-01-27 10:50:55 -08:00
Gene S d331367223 a few small fixes 2016-01-27 10:39:24 -08:00
Gene S 156f1f50bc visual improvements and fixes 2016-01-26 19:16:39 -08:00
Gene S 3acd66e5b3 removed bootstrap dependencies 2016-01-26 17:27:29 -08:00
or-else 876a7c1b1f removed bootstrap 2016-01-24 22:23:28 -08:00
or-else 444d7c006d lots of refactoring to remove bootstrap, still unfinished 2016-01-24 22:13:50 -08:00
Gene S 10353c9a1d refactoring message view (incomplete) 2016-01-22 18:00:56 -08:00
Gene S 22e2be2dc8 online presence 2016-01-20 19:07:36 -08:00
Gene S d3e2436527 Merge branch 'master' of https://github.com/tinode/example-react-js 2016-01-20 10:24:30 -08:00
Gene S 984f255d8a debigging 2016-01-20 10:24:24 -08:00
or-else 3f508da8e6 lots of refactoring to support read/received counts 2016-01-18 21:38:53 -08:00
or-else 295ffd640b lots of refactoring to support read/received counts 2016-01-17 15:59:07 -08:00
Gene S b344f9d7e4 Merge branch 'master' of https://github.com/tinode/example-react-js 2016-01-15 16:46:50 -08:00
Gene S ca49c83073 account creation works now 2016-01-15 16:46:24 -08:00
or-else d28d74a77a lass padding in contact list 2016-01-14 20:51:27 -08:00
Gene S 1b52fde005 README update 2016-01-14 19:10:14 -08:00
Gene S 31d5320922 bug fixes and typing notifications 2016-01-14 17:12:03 -08:00
Gene S e871dad863 now fetching and rendering messages 2016-01-13 17:58:41 -08:00
Gene S eee2db628a fetching messages from the server 2016-01-12 18:57:34 -08:00
or-else 4c759913c7 making contact list scrollable 2016-01-11 22:01:28 -08:00
or-else 4442cbae9d making contacts scrollable 2016-01-10 19:46:50 -08:00
or-else 6d0d75ab1d making contacts scrollable 2016-01-10 19:33:19 -08:00
or-else 3f2746cdb7 contacts loaded and shown 2016-01-10 16:01:44 -08:00
or-else d28c696190 continue to hook up server 2016-01-10 14:07:25 -08:00
or-else eba7510be8 adding subscription (incomplete) 2016-01-09 21:59:36 -08:00
Gene S d1442bfc93 hooked up to the server and added login error handling 2016-01-08 18:26:08 -08:00
Gene S 743d941204 hooked up the Tinode bindings, it calls the server now 2016-01-07 18:18:56 -08:00
Gene S f82bd966e0 made demo available online 2016-01-06 10:54:14 -08:00
Gene S aedc9854c1 made demo available online 2016-01-06 10:53:14 -08:00
Gene S 87c5b5bc6b graphic assets 2016-01-05 18:48:40 -08:00
Gene S 9f50eff10a moved all logic to AppView, added Sign Up view 2016-01-05 18:47:37 -08:00
Gene S 3b56e7ca2f moved files around for clarity 2016-01-05 11:07:55 -08:00
Gene S f64c8082ff daily commit 2016-01-04 19:12:31 -08:00
or-else 20be763dc1 daily commit 2016-01-03 20:49:32 -08:00
or-else 391a956af8 daily commit 2016-01-02 20:16:30 -08:00
or-else 2121a6a4f2 daily commit 2016-01-01 21:36:34 -08:00
Gene Sokolov dc8f82961a daily commit 2016-01-01 20:48:38 -08:00
Gene S d9015804c8 current status 2015-12-31 15:10:26 -08:00
Gene S 135bec17a8 Merge branch 'master' of https://github.com/tinode/react-js 2015-12-31 15:08:24 -08:00
Gene S 35624786ab Initial commit 2015-12-31 15:07:38 -08:00
Gene S 0688a360c7 initial pass at a react.js chat 2015-12-31 15:03:22 -08:00
8 changed files with 2628 additions and 139 deletions
-138
View File
@@ -1,138 +0,0 @@
# ---> Node
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
# vitepress build output
**/.vitepress/dist
# vitepress cache directory
**/.vitepress/cache
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
+17 -1
View File
@@ -1,2 +1,18 @@
# im_webapp
# Single-page chat with Tinode
Example using [Tinode](https://github.com/tinode/chat/) to build a single-page chat application. The app uses
[React](https://facebook.github.io/react/), Google's material design [fonts](https://www.google.com/fonts/)
and [icons](https://google.github.io/material-design-icons/#icon-font-for-the-web). The [Tinode javascript library](https://github.com/tinode/tinode-js/) has no external dependencies.
This is work in progress. Bugs are expected. The app was tested in the latest Chrome & Firefox only.
Try it at http://api.tinode.co/x/example-react-js/. Login as one of `alice`, `bob`, `carol`, `dave`, `frank`.
Password is `<login>123`, e.g. login for `alice` is `alice123`.
License: [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0)
Photos from https://www.pexels.com/ under [CC0 license](https://www.pexels.com/photo-license/).
Background pattern from http://subtlepatterns.com/, commercial and non-commercial use allowed with attribution.
![App screenshot](pic-20160130.png)
+740
View File
@@ -0,0 +1,740 @@
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
/* Basic elements defined */
html, body {
height:100%;
width:100%;
font-family: 'Roboto', Arial, sans-serif;
font-size: 10pt;
color: #666;
overflow: hidden;
background-color: silver;
box-shadow: inset 0 10rem #3949AB; /* the deep-plue stripe accross the top */
}
a {
color: #2196f3;
text-decoration: none;
}
a:hover,
a:focus {
color: #0a6ebd;
text-decoration: underline;
}
a:focus {
outline: thin dotted;
outline: 5px auto -webkit-focus-ring-color;
outline-offset: -2px;
}
form {
font-size: 1.2rem;
}
form label {
font-size: 1rem;
}
/* Input fields and buttons */
button {
display: inline-block;
font-family: inherit;
font-size: 1.1rem;
height: 2.2em;
line-height: 2.2em;
font-weight: normal;
text-align: center;
vertical-align: middle;
touch-action: manipulation;
cursor: pointer;
border: 1px solid transparent;
white-space: nowrap;
padding-left: 2em;
padding-right: 2em;
border-radius: 2px;
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.25);
text-transform: uppercase;
}
button[disabled],
html input[disabled] {
cursor: default;
opacity: 0.65;
box-shadow: none;
}
button.round {
border-radius: 50%;
width: 3rem;
height: 3rem;
padding: 0;
margin: 0;
line-height: 3.5rem;
outline: none; /* otherwise a square outline is shown */
box-shadow: 0 2px 0.5rem 0 rgba(0, 0, 0, 0.25);
z-index: 2;
}
button.round.small {
width: 2rem;
height: 2rem;
line-height: 2rem;
box-shadow: 0 2px 0.35rem 0 rgba(0, 0, 0, 0.25);
}
button:focus, button:hover, button:active {
color: #fff;
}
button:active {
box-shadow: inset 0 3px 0.5rem rgba(0, 0, 0, 0.125);
}
button:active.round.small {
box-shadow: inset 0 2px 0.35rem rgba(0, 0, 0, 0.125);
}
button.blue {
background-color: #1e88e5; /* blue 600 */
color: white;
}
button.blue:focus, button.blue:hover, button.blue:active {
background-color: #1976d2;
}
button.blue {
background-color: #1e88e5; /* blue 600 */
color: white;
}
button.blue:focus, button.blue:hover, button.blue:active {
background-color: #1976d2;
}
button.white {
background-color: #FFF;
color: #2196f3; /* blue 500 */
}
button.white:focus, button.white:hover, button.blue:active {
background-color: #e3f2fd;
}
textarea, input {
font-family: inherit;
font-size: 1.05rem;
background: transparent;
border: none;
margin: 0.25rem 0;
padding: 0 0.125rem;
outline: none;
box-sizing: border-box;
color: #666;
}
textarea {
resize: none;
}
input[type="text"],
input[type="password"],
textarea {
height: 2.5rem;
border-bottom: 1px solid #ccc;
border-radius: 0.2rem;
box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
transition: all 0.2s ease-in-out;
width: 100%;
}
textarea:focus,
input[type="text"]:focus,
input[type="password"]:focus {
border-bottom: 1px solid #2196f3;
box-shadow: 0 1px 0 rgba(33, 150, 243, 0.25);
}
/* Scrollbar styling for Chrome. Firefox does not support scrollbar styling. */
::-webkit-scrollbar {
width: 0.6rem;
}
::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.2);
background-color: rgba(255,255,255,0.1);
}
::-webkit-scrollbar-thumb {
background-color: rgba(0,0,0,0.3);
}
/* END of input and buttons */
form {
padding: 0.5rem 0.75rem;
line-height: 1.75;
font-size: 1.2rem;
}
/* END of basic elements */
#mountPoint {
height: 100%;
padding-top: 1rem;
padding-bottom: 3rem;
}
/* Top-level application layout style: sidepanel + main view */
#app-container {
position: relative;
display: flex;
height: 100%;
max-width: 80rem;
overflow: hidden;
margin-left: auto;
margin-right: auto;
border-radius: 0.25rem;
box-shadow: 1px 2px 0.3rem gray;
background-color: white;
}
#sidepanel {
position: relative;
display: flex;
flex-direction: column;
width: 24rem;
min-width: 24rem;
height: 100%;
}
#topic-view {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
@media (max-width: 960px) {
#mountPoint {
padding: 0;
}
}
@media (max-width: 640px) {
#app-container {
width: 100%;
}
#sidepanel {
width: 100%;
}
}
/* Class to alternatively hide sidepanel/topic-view */
.nodisplay {
display: none!important;
}
/* END of top-level layout */
/* Sidepanel styles */
.panel-title {
font-size: 1.4rem;
}
.dialog-buttons {
display: flex;
padding: 0.5em;
justify-content: flex-end;
}
#side-caption-panel {
display: flex;
align-items: center;
flex: none;
padding: 0.5em;
height: 4em;
background-color: #2196f3; /* blue 500 */
color: #bbdefb; /* light-blue 100 */
box-shadow: 0 1px 2px gray;
z-index: 1; /* otherwise the shadow becomes invisible */
}
#side-caption-panel a {
color: #bbdefb; /* blue 100 */
padding-left: 0.5em;
vertical-align: -1em; /* icons are bigger than the declared font size */
}
#side-caption-panel :hover {
color: white;
}
#sidepanel-title {
margin-right: auto;
margin-left: 0.5em;
}
#self-avatar {
width: 3rem;
height: auto;
flex: none;
border-radius: 33%;
}
/* Application settings */
#settings-form ul {
list-style: none;
}
#settings-form li {
vertical-align: middle;
}
#settings-form label {
display: inline-block;
padding-left: 0.5rem;
}
/* Area which displays an error message */
#alert-box {
padding: 0.5em;
background-color: transparent;
}
#alert-box.error-alert {
background-color: #ffcdd2;
border-color: #d32f2f;
color: #600;
}
/* List of contacts */
#contacts-panel {
overflow-y: auto;
margin-bottom: auto;
height: 100%;
}
#contact-box {
list-style: none;
}
#contact-box li {
display: flex;
padding: 0.35rem 0.25rem 0.5rem 0.35rem;
min-height: 3.5rem;
overflow: hidden;
}
#contact-box li:hover {
background-color: #eceff1; /* blue-gray 50 highlight */
}
#contact-box li.selected {
background-color: #cfd8dc; /* blue-gray 100 highlight */
}
#contact-box .contact-title {
font-size: 1.05rem;
}
/* Avatar and online-offline indicator */
#contact-box .avatar-box {
margin-right: 0.35rem;
position: relative;
width: 3rem;
height: 3rem;
overflow: hidden;
padding: 0;
}
#contact-box .avatar {
width: 3rem;
height: auto;
border-radius: 40%;
}
/* Online-offline indicator positioned inside avatar-box */
#contact-box .online, .offline {
font-size: 1.5em;
line-height: 1;
position: absolute;
right: -0.1rem;
bottom: -0.1rem;
}
#contact-box .online {
color: #4caf50;
}
#contact-box .offline {
color: #888;
}
#add-topic {
position: absolute;
right: 1em;
bottom: 1em;
}
/* END of avatar box */
/* New account panel (signup form) */
#signup-form {
display: flex;
flex-direction: column;
}
#signup-form-one {
display: flex;
justify-content: space-between;
align-items: center;
}
/* Styling of avatar upload area in the New Account panel */
.avatar-upload {
position: relative;
text-align: center;
vertical-align: middle;
width: 4.5rem;
height: auto;
box-sizing: border-box;
margin-left: 0.5rem;
padding: 0;
}
.avatar-upload .blank {
border: 1px dashed #999;
border-radius: 0.75rem;
font-size: 1rem;
width: 4.5rem;
height: 4.5rem;
overflow: hidden;
color: #999;
vertical-align: middle;
line-height: 4.5rem;
box-sizing: border-box;
margin: 0;
padding: 0;
}
.avatar-upload .preview {
border-radius: 0.75rem;
width: 4.5rem;
height: 4.5rem;
overflow: hidden;
box-sizing: border-box;
margin: 0;
padding: 0;
}
.avatar-upload .inputfile.hidden {
width: 0.1px;
height: 0.1px;
opacity: 0;
overflow: hidden;
position: absolute;
}
.avatar-upload .inputfile + label.round {
display: inline-block;
vertical-align: middle;
text-align: center;
cursor: pointer;
width: 2.5rem;
height: 2.5rem;
line-height: 3rem;
border-radius: 50%;
box-shadow: 0 1px 4px rgba(0,0,0,0.4);
position: absolute;
top: 3.875rem;
left: 1rem;
background-color: #fafafa;
}
.avatar-upload .inputfile:focus + label.round {
outline: none;
}
.avatar-upload .inputfile:focus + label,
.avatar-upload .inputfile + label:hover {
background-color: #e3f2fd;
color: #42a5f5;
}
/* END of avatar upload */
/* END of new account panel */
/* END of sidepanel styles */
/* Topic/messages view */
#topic-caption-panel {
display: flex;
align-items:center;;
justify-content: flex-start;
flex: none;
padding: 0.5rem;
height: 4rem;
background-color: #b0bec5;
box-shadow: 0 1px 2px gray;
z-index: 1; /* otherwise the shadow becomes invisible */
}
#hide-message-view {
display: block;
margin-right: 0.5rem;
}
#topic-users {
margin-left: auto;
}
/* Scrollable panel where the messages are shown */
#messages-panel {
padding: 0.75rem;
overflow-y: scroll;
background-color: #eceff1;
height: 100%;
background-image: url("../img/ignasi_pattern_s.png");
}
/* Footer-panel with the input for the new message */
#send-message-panel {
display: flex;
align-items: center;
flex: none;
padding: 0.5rem;
background-color: #eceff1;
box-shadow: 0 -1px rgba(0,0,0,0.1); /* Faint shadow above panel */
z-index: 2;
}
/* A static panel shown when no topic is selected */
#dummy-view {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: #e0f7fa;
}
#dummy-view a {
text-decoration: none;
display: block;
text-align: center;
vertical-align: middle;
}
/* Talk bubbles */
.chat-box {
list-style: none;
padding: 0 0 3.5rem 0;
margin: 0 0.5rem;
}
.chat-box li {
display: flex;
margin: 0;
padding: 0;
align-items: flex-end;
}
.chat-box li.right {
justify-content: flex-end;
}
.chat-box .bubble {
position: relative;
max-width: 40rem;
min-width: 12rem;
height: auto;
padding: 0.75rem 0.5rem 0.75rem 1.25rem;
margin: 0;
text-align: left;
border-radius: 0.5rem;
-webkit-border-radius: 0.5rem;
-moz-border-radius: 0.5rem;
/* tested in chrome 47 on mac - performance sucks
-webkit-filter: drop-shadow(0px 1px 1px -1px rgba(0,0,0,0.3));
-filter: drop-shadow(0px 1px 1px -1px rgba(0,0,0,0.3));
*/
}
.chat-box li.single {
margin-top: 0.75rem;
margin-bottom: 0.75rem;
}
.chat-box li.first {
margin-top: 0.75rem;
margin-bottom: 0.15rem;
}
.chat-box li.middle {
margin-top: 0.15rem;
margin-bottom: 0.15rem;
}
.chat-box li.last {
margin-top: 0.15rem;
margin-bottom: 0.75rem;
}
/* Left triangle placed bottom left flush. */
.chat-box li.left .tip::before {
content: '';
position: absolute;
width: 0;
height: 0;
right: auto;
left: -10px;
top: auto;
bottom: 0;
border: 10px solid;
border-top-color: transparent;
border-right-color: transparent;
border-bottom-color: inherit;
border-left-color: transparent;
}
/* Right triangle placed bottom right flush. */
.chat-box li.right .tip::before {
content: '';
position: absolute;
display: flex;
justify-content: space-between;
width: 0;
height: 0;
left: auto;
right: -10px;
top: auto;
bottom: 0;
border: 10px solid;
border-top-color: transparent;
border-right-color: transparent;
border-bottom-color: inherit;
border-left-color: transparent;
}
.chat-box .avatar-box {
width: 3rem;
text-align: center;
}
.chat-box .avatar-box img {
width: 2.4rem;
display: block;
position: relative;
left: 0.3rem;
border-radius: 33%;
}
.chat-box .bubble p {
display: flex;
justify-content: space-between;
margin: 0;
}
.chat-box .timestamp {
display: inline-block;
font-size: 80%;
color: #777;
padding-left: 1.5em;
padding-top: 0.5em;
white-space: nowrap;
}
/* Typing notification bubble */
.chat-box .typing {
display: inline-block;
border-radius: 0.5rem;
width: 2rem;
padding: 0.25rem 0.35rem;
vertical-align: middle;
text-align: center;
color: #aaa;
margin-top: 0.75rem;
}
/* END of talk bubbles */
/* END of topic/mesages view */
/* Modal dialog */
.dialog-overlay {
position: absolute;
display: flex;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 10;
background-color: rgba(0,0,0,0.25);
}
.modal-dialog {
display: flex;
flex-direction: column;
justify-content: space-between;
background-color: white;
min-width: 24rem;
min-height: 16rem;
margin: auto;
border-radius: 0.3rem;
box-shadow: 0 0.5rem 1rem 0 rgba(0,0,0, 0.25);
}
.modal-dialog .title-panel {
display: flex;
justify-content: space-between;
font-size: 1.4rem;
padding: 1rem;
}
.modal-dialog .body-panel {
margin: auto 0.5rem auto 0.5rem;
}
.modal-dialog .dialog-buttons {
border-top: 1px solid #f5f5f5;
background-color: #fafafa
}
.modal-dialog .dialog-buttons a {
display: inline-block;
text-transform: uppercase;
text-decoration: none;
font-size: 1.1rem;
padding: 0.35rem 1.5rem;
}
/* END of modal dialog */
/* Miscellaneous */
/* Badge with the number of unread messages */
.badge {
display: inline-block;
font-size: 0.8rem;
font-weight: bold;
background-color: #0097A7;
color: white;
border-radius: 1em;
padding: 0.25em;
min-width: 1.75em;
text-align: center;
}
/* Color of buttons */
.blue {
color: #2196f3; /* blue 500 */
}
/* Material icons resized from the default 24pt */
.material-icons {
font-size: 1.4rem;
line-height: 1;
}
.material-icons.small {
font-size: 1rem;
}
#self-avatar.material-icons, .avatar-box .material-icons {
font-size: 2.8rem;
}
.avatar-box .material-icons {
color: rgba(250, 250, 250, 0.8); /* #fafafa, gray 50 */
background-color: #e0e0e0;
border-radius: 40%;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

+554
View File
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 119 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

+1317
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 981 KiB