diff --git a/ChatUIClass.php b/ChatUIClass.php new file mode 100644 index 0000000..75be514 --- /dev/null +++ b/ChatUIClass.php @@ -0,0 +1,109 @@ + $roleVal) + { + $tempCast = []; + $tempArray = explode(":",$roleVal); + list($name, ,$img) = $tempArray; + $tempCast['name'] = $name; + $tempCast['img'] = $img; + array_push($chat['roles'],$tempCast); + } + // structure lines + $linesArray = array_values(array_filter(explode(PHP_EOL,$linesData))); + foreach($linesArray as $lineKey => $lineVal) + { + if($lineVal != '---') + { + $chat['dialog'] = $chat['dialog'] + 1; + $tempLine = []; + $tempArray = explode(":",$lineVal); + list($name, $sentence) = $tempArray; + $tempLine['name'] = $name; + $tempLine['sentence'] = $sentence; + array_push($chat['lines'],$tempLine); + } + } + // var_dump($chat); + $this->dialogue = $chat; + } + public function read(){ + $tempHtml = ''; + foreach($this->dialogue['lines'] as $dialogue) + { + switch($dialogue['name']) + { + case 'Narator': + $tempHtml .= $this->role_narator($dialogue); + break; + case $this->dialogue['roles'][0]['name']: + $tempHtml .= $this->role_rightSide($dialogue); + break; + default: + $tempHtml .= $this->role_leftSide($dialogue); + break; + } + } + return $tempHtml; + } + private function role_narator($dialogue) + { + $tempHtml = '

'.$dialogue['sentence'].'

'; + return $tempHtml; + } + private function role_leftSide($dialogue) + { + $tempHtml = '
'; + $tempHtml .= '
'; + $tempHtml .= ''.$dialogue['name']; + $tempHtml .= '
'; + $tempHtml .= '

'.$dialogue['sentence'].'

'; + $tempHtml .= '
'; + return $tempHtml; + } + private function role_rightSide($dialogue) + { + $tempHtml = '
'; + $tempHtml .= '
'; + $tempHtml .= $dialogue['name'].''; + $tempHtml .= '
'; + $tempHtml .= '

'.$dialogue['sentence'].'

'; + $tempHtml .= '
'; + return $tempHtml; + } + private function loadChatHeaderImg($castName) + { + foreach($this->dialogue['roles'] as $cast) + { + if($cast['name'] == $castName) + { + return $cast['img']; + } + } + } +} // EOF +?> \ No newline at end of file diff --git a/README.md b/README.md index 7325c44..235f29f 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,36 @@ # PHP Chat UI - PHP Class for simulate conversation dialog +PHP Class for simulate conversation dialog. + +A UI component for conversational novel community. + +Author: Tang Hoong + +# Screenshot + +![](sample-02.png "sample") + +# Description +Just dump the string format which same as sample.txt then ChatUIClass will render them perfect and nice. + +# How +Follow the format from sample.txt: +``` +Snake: https://i.imgur.com/FEiFVeO.png +--- +Narator: Once upon a time... +Snake: Wanna eat apple 苹果 🍎🍎🍎? +``` +then +``` +include 'ChatUIClass.php'; +$sample = file_get_contents('./sample.txt'); +$dialogue = new ChatUI($sample); +echo $dialogue->read(); +``` +become + +![](sample-01.png "sample") + +# Resources refer from: + +[Codepen IMessage css](https://codepen.io/AllThingsSmitty/pen/jommGQ?editors=1000) \ No newline at end of file diff --git a/imessage.css b/imessage.css new file mode 100644 index 0000000..afc68b2 --- /dev/null +++ b/imessage.css @@ -0,0 +1,206 @@ +.imessage { + background-color: #fff; + /* border: 1px solid #e5e5ea; */ + border-radius: 0.25rem; + display: flex; + flex-direction: column; + font-family: "SanFrancisco"; + font-size: 1.25rem; + margin: 0 auto 1rem; + max-width: 600px; + padding: 0.5rem 1.5rem; + } + + .imessage p { + border-radius: 1.15rem; + line-height: 1.25; + max-width: 75%; + padding: 0.5rem .875rem; + position: relative; + word-wrap: break-word; + } + + .imessage p::before, + .imessage p::after { + bottom: -0.1rem; + content: ""; + height: 1rem; + position: absolute; + } + + p.from-me { + align-self: flex-end; + background-color: #248bf5; + color: #fff; + } + + p.from-me::before { + border-bottom-left-radius: 0.8rem 0.7rem; + border-right: 1rem solid #248bf5; + right: -0.35rem; + transform: translate(0, -0.1rem); + } + + p.from-me::after { + background-color: #fff; + border-bottom-left-radius: 0.5rem; + right: -40px; + transform:translate(-30px, -2px); + width: 10px; + } + + p[class^="from-"] { + margin: 0.5rem 0; + width: fit-content; + } + + p.from-me ~ p.from-me { + margin: 0.25rem 0 0; + } + + p.from-me ~ p.from-me:not(:last-child) { + margin: 0.25rem 0 0; + } + + p.from-me ~ p.from-me:last-child { + margin-bottom: 0.5rem; + } + + p.from-them { + align-items: flex-start; + background-color: #e5e5ea; + color: #000; + } + + p.from-them:before { + border-bottom-right-radius: 0.8rem 0.7rem; + border-left: 1rem solid #e5e5ea; + left: -0.35rem; + transform: translate(0, -0.1rem); + } + + p.from-them::after { + background-color: #fff; + border-bottom-right-radius: 0.5rem; + left: 20px; + transform: translate(-30px, -2px); + width: 10px; + } + + p[class^="from-"].emoji { + background: none; + font-size: 2.5rem; + } + + p[class^="from-"].emoji::before { + content: none; + } + + .no-tail::before { + display: none; + } + + .margin-b_none { + margin-bottom: 0 !important; + } + + .margin-b_one { + margin-bottom: 1rem !important; + } + + .margin-t_one { + margin-top: 1rem !important; + } + + + /* general styling */ + @font-face { + font-family: "SanFrancisco"; + src: + url("https://cdn.rawgit.com/AllThingsSmitty/fonts/25983b71/SanFrancisco/sanfranciscodisplay-regular-webfont.woff2") format("woff2"), + url("https://cdn.rawgit.com/AllThingsSmitty/fonts/25983b71/SanFrancisco/sanfranciscodisplay-regular-webfont.woff") format("woff"); + } + + body { + font-family: -apple-system, + BlinkMacSystemFont, + "Segoe UI", + Roboto, + Oxygen-Sans, + Ubuntu, + Cantarell, + "Helvetica Neue", + sans-serif; + font-weight: normal; + margin: 0; + } + + .container { + margin: 0 auto; + max-width: 600px; + padding: 1rem; + } + + h1 { + font-weight: normal; + margin-bottom: 0.5rem; + } + + h2 { + border-bottom: 1px solid #e5e5ea; + color: #666; + font-weight: normal; + margin-top: 0; + padding-bottom: 1.5rem; + } + + .comment { + color: #222; + font-size: 1.25rem; + line-height: 1.5; + margin-bottom: 1.25rem; + max-width: 100%; + padding: 0; + } + + @media screen and (max-width: 800px) { + body { + margin: 0 0.5rem; + } + + .container { + padding: 0.5rem; + } + + .imessage { + font-size: 1.05rem; + margin: 0 auto 1rem; + max-width: 600px; + padding: 0.25rem 0.875rem; + } + + .imessage p { + margin: 0.5rem 0; + } + } + + + /* chat-header */ + .imessage .chat-header { + border-radius: 30px; + width: 20px; + height: 20px; + margin: 3px; +} +.imessage .chat-name{ + font-weight: bold; + display: flex; + align-items: center; +} +.imessage .chat-name-me{ + text-align: right; + justify-content: flex-end; +} +.imessage .chat-name-them{ + text-align: left; +} \ No newline at end of file diff --git a/index.php b/index.php new file mode 100644 index 0000000..8f91950 --- /dev/null +++ b/index.php @@ -0,0 +1,30 @@ + + + + + + + + + + + + + Text soap + + + + + +
+

Text Soap

+ read(); + ?> +
+ + \ No newline at end of file diff --git a/sample-01.png b/sample-01.png new file mode 100644 index 0000000..c18fad3 Binary files /dev/null and b/sample-01.png differ diff --git a/sample-02.png b/sample-02.png new file mode 100644 index 0000000..57f9d01 Binary files /dev/null and b/sample-02.png differ diff --git a/sample.txt b/sample.txt new file mode 100644 index 0000000..39d0d7e --- /dev/null +++ b/sample.txt @@ -0,0 +1,16 @@ +Adam: https://i.imgur.com/pW71NE5.jpeg +Eve: https://i.imgur.com/Jvh1OQm.jpeg +Snake: https://i.imgur.com/FEiFVeO.png +--- +Narator: Once upon a time... +Snake: Wanna eat apple 苹果 🍎🍎🍎? +Eve: Ya sure, why not? why not? why not? why not? why not? why not? why not? why not? why not? why not? why not? +Narator: Eve took the apple and bite. +Adam: Dont! Dont! Dont! Dont! Dont! Dont! Dont! Dont! Dont! +Snake: It is too late! hahaha! +Narator: Thats why human have been cast away away away away away away away away away away away away away. +Narator: Thats why human have been cast away. +Narator: Thats why human have been cast away. +Narator: Thats why human have been cast away. +Narator: Thats why human have been cast away. +Narator: end of the story.FIN.👍 \ No newline at end of file