diff --git a/ChatUIClass.php b/ChatUIClass.php
deleted file mode 100644
index 75be514..0000000
--- a/ChatUIClass.php
+++ /dev/null
@@ -1,109 +0,0 @@
- $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 = '
';
- 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 235f29f..77452a1 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,7 @@
-# PHP Chat UI
-PHP Class for simulate conversation dialog.
-
+# PHP Chat Block
+A dialogue chat block display component for php project.
A UI component for conversational novel community.
-
+Date: 30 Aug, 2021
Author: Tang Hoong
# Screenshot
@@ -10,7 +9,7 @@ Author: Tang Hoong

# Description
-Just dump the string format which same as sample.txt then ChatUIClass will render them perfect and nice.
+Just dump the string format which exactly same as sample.txt then ChatBlock will render them into perfect and nice chat blocks.
# How
Follow the format from sample.txt:
@@ -22,10 +21,10 @@ Snake: Wanna eat apple čšć đđđ?
```
then
```
-include 'ChatUIClass.php';
-$sample = file_get_contents('./sample.txt');
-$dialogue = new ChatUI($sample);
-echo $dialogue->read();
+include 'ChatBlock.php';
+$lines = file_get_contents('./chapter-1.txt');
+$cb = new ChatBlock($lines);
+echo $cb->read();
```
become
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..e6f6eb1
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,15 @@
+{
+ "name": "tanghoong/php-chat-block",
+ "description": "an dialogue chat block display component for php project",
+ "type": "library",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Tang Hoong",
+ "email": "tanghoong.com@gmail.com"
+ }
+ ],
+ "require": {
+ "php": ">=7.1"
+ }
+}
\ No newline at end of file
diff --git a/index.php b/demo.php
similarity index 79%
rename from index.php
rename to demo.php
index 8f91950..d9355aa 100644
--- a/index.php
+++ b/demo.php
@@ -1,6 +1,9 @@
@@ -20,10 +23,10 @@
-
Text Soap
+ ćčľĺŽŁč¨#1
read();
+ $cb = new ChatUI($sample);
+ echo $cb->read();
?>
diff --git a/imessage.css b/imessage.css
index afc68b2..4c50b58 100644
--- a/imessage.css
+++ b/imessage.css
@@ -203,4 +203,68 @@
}
.imessage .chat-name-them{
text-align: left;
+}
+
+.imessage .text-center{
+ text-align: center;
+}
+
+.imessage .text-bold{
+ font-weight: bold;
+}
+
+.imessage .text-muted{
+ font-size: 12px;
+ margin: 5px;
+}
+
+.container-image{
+ padding: 30px;
+}
+
+.container-image img{
+ border-radius: 1.15rem;
+}
+.container-mp3{
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ color: #000;
+ border-radius: 1.15rem;
+ line-height: 1.25;
+ padding: 0.5rem .875rem;
+ position: relative;
+ word-wrap: break-word;
+ font-size: 12px;
+ margin: 5px;
+}
+.container-youtube{
+ height: 300px;
+ width: 400px;
+ margin: 0px auto;
+}
+.container-youtube iframe{
+ border-radius: 1.15rem;
+}
+.container-decision{
+ display: flex;
+ justify-content: space-between;
+}
+
+.container-decision .decision-option{
+ cursor: pointer;
+ background-color: #e5e5ea;
+ color: #000;
+ border-radius: 1.15rem;
+ line-height: 1.25;
+ padding: 0.5rem .875rem;
+ margin: 0 auto 1rem;
+ position: relative;
+ word-wrap: break-word;
+ text-align: center;
+}
+
+.container-decision .decision-option:focus,
+.container-decision .decision-option:hover{
+ background-color: #bdbdbe;
}
\ No newline at end of file
diff --git a/old/chat-ui.css b/old/chat-ui.css
new file mode 100644
index 0000000..25c0ac3
--- /dev/null
+++ b/old/chat-ui.css
@@ -0,0 +1,62 @@
+#chatUI{
+ padding: 10px;
+ background-color: white;
+}
+
+#chatUI .chat-header{
+ border-radius: 30px;
+ width: 20px;
+ height: 20px;
+ margin: 3px;
+}
+
+#chatUI .chat-container{
+ white-space: pre-wrap;
+ border-radius: 5px;
+ margin: 10px;
+ padding: 5px;
+}
+
+#chatUI .chat-container-me{
+ background-color: #d5fdf0;
+ margin-left: 40%;
+}
+
+#chatUI .chat-container-them{
+ background-color: #2db688;
+ margin-right: 40%;
+}
+
+#chatUI .chat-container .chat-name{
+ font-weight: bold;
+ display: flex;
+ align-items: center;
+}
+#chatUI .chat-container .chat-name-me{
+ text-align: right;
+ justify-content: flex-end;
+}
+#chatUI .chat-container .chat-name-them{
+ text-align: left;
+}
+
+#chatUI .chat-container .chat-block{
+ margin: 5px 0px;
+}
+#chatUI .chat-container .chat-block-me{
+ text-align: right;
+}
+#chatUI .chat-container .chat-block-them{
+ text-align: left;
+}
+
+#chatUI .chat-block-system{
+ text-align: center;
+ white-space: pre-wrap;
+ margin-left: 20%;
+ margin-right: 20%;
+ background-color: #cccccc;
+ padding: 10px;
+ border-radius: 5px;
+ margin-bottom: 10px;
+}
diff --git a/sample.txt b/sample.txt
index 39d0d7e..3a18e54 100644
--- a/sample.txt
+++ b/sample.txt
@@ -1,16 +1,27 @@
-Adam: https://i.imgur.com/pW71NE5.jpeg
-Eve: https://i.imgur.com/Jvh1OQm.jpeg
-Snake: https://i.imgur.com/FEiFVeO.png
+Adam: //i.imgur.com/pW71NE5.jpeg?color=red
+Eve: //i.imgur.com/Jvh1OQm.jpeg?color=blue
+Snake: //i.imgur.com/FEiFVeO.png?color=green
---
+Background: //filesamples.com/samples/audio/mp3/sample3.mp3
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
+Tiger: It is too late! hahaha!
+Dog: It is too late! hahaha!
+Cat: 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 Here have been cast away.
+Narator: Thats why human
have been cast away.
+
+Narator: end of the story.FIN.đ
+
+
+Image: //i.imgur.com/pW71NE5.jpeg?color=red
+MP3: //filesamples.com/samples/audio/mp3/sample3.mp3
+Youtube: //www.youtube.com/embed/tgbNymZ7vqY?controls=0
+Decision: 塌螚,ä¸é´,ĺłčžš,ä¸é˘,ä¸é˘
+
diff --git a/src/ChatBlock.php b/src/ChatBlock.php
new file mode 100644
index 0000000..a998b87
--- /dev/null
+++ b/src/ChatBlock.php
@@ -0,0 +1,205 @@
+ $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);
+ }
+ }
+ $this->dialogue = $chat;
+ }
+ /**
+ * To allow using as Json format for frontend rendering
+ */
+ public function json(){
+ return json_encode($this->dialogue);
+ }
+ /**
+ * Using default html rendered chat blocks
+ */
+ public function read(){
+ $tempHtml = '';
+ foreach($this->dialogue['lines'] as $dialogue)
+ {
+ switch($dialogue['name'])
+ {
+ case 'Narator':
+ $tempHtml .= $this->role_narator($dialogue);
+ break;
+ case 'Image':
+ $tempHtml .= $this->render_image_holder($dialogue);
+ break;
+ case 'MP3':
+ case 'Background':
+ $tempHtml .= $this->render_sound_holder($dialogue);
+ break;
+ case 'Youtube':
+ $tempHtml .= $this->render_video_holder($dialogue);
+ break;
+ case 'Decision':
+ $tempHtml .= $this->render_decisions_holder($dialogue);
+ break;
+ case $this->dialogue['roles'][0]['name']:
+ $tempHtml .= $this->role_rightSide($dialogue);
+ break;
+ default:
+ $tempHtml .= $this->role_leftSide($dialogue);
+ break;
+ }
+ }
+ return $tempHtml;
+ }
+ // Multimedia
+ private function render_image_holder($dialogue)
+ {
+ $link = $this->fn_valid_link($dialogue['sentence']);
+ $tempHtml = '';
+ $tempHtml .= '

';
+ $tempHtml .= '
';
+ return $tempHtml;
+ }
+ private function render_sound_holder($dialogue)
+ {
+ $link = $this->fn_valid_link($dialogue['sentence']);
+ $tempHtml = '';
+ $tempHtml .= '
';
+ if($dialogue['name'] == 'Background')
+ {
+ $tempHtml .= '
Background Music
';
+ }
+ $tempHtml .= '
';
+ return $tempHtml;
+ }
+ private function render_video_holder($dialogue)
+ {
+ $link = $this->fn_valid_link($dialogue['sentence']);
+ $tempHtml = '';
+ $tempHtml .= '';
+ $tempHtml .= '
';
+ return $tempHtml;
+ }
+ private function render_decisions_holder($dialogue)
+ {
+ $optionList = explode(',',$dialogue['sentence']);
+ $tempHtml = '';
+ $tempHtml .= '';
+ foreach($optionList as $option)
+ {
+ $tempHtml .= '
'.$option.'
';
+ }
+ $tempHtml .= '
';
+ return $tempHtml;
+ }
+ // Misc
+ private function fn_filter($dialogue)
+ {
+ $newStr = strip_tags($dialogue,"");
+ return trim($newStr);
+ }
+ private function fn_valid_link($dialogue)
+ {
+ return $dialogue;
+ // $url = filter_var($dialogue, FILTER_SANITIZE_URL);
+ // if (filter_var($url, FILTER_VALIDATE_URL)) {
+ // return $url;
+ // }
+ // return false;
+ }
+ // Chat Blocks
+ private function role_narator($dialogue)
+ {
+ $sentence = $this->fn_filter($dialogue['sentence']);
+ $tempHtml = '';
+ return $tempHtml;
+ }
+ private function role_leftSide($dialogue)
+ {
+ $sentence = $this->fn_filter($dialogue['sentence']);
+ $tempHtml = '';
+ $tempHtml .= '
';
+ $chatHeaderImg = $this->loadChatHeaderImg($dialogue['name']);
+ if($chatHeaderImg == false)
+ {
+ $tempHtml .= $dialogue['name'];
+ }else{
+ $tempHtml .= ''.$dialogue['name'];
+ }
+ $tempHtml .= '
';
+ $tempHtml .= '
'.$sentence.'
';
+ $tempHtml .= '
';
+ return $tempHtml;
+ }
+ private function role_rightSide($dialogue)
+ {
+ $sentence = $this->fn_filter($dialogue['sentence']);
+ $tempHtml = '';
+ $tempHtml .= '
';
+ $chatHeaderImg = $this->loadChatHeaderImg($dialogue['name']);
+ if($chatHeaderImg == false)
+ {
+ $tempHtml .= $dialogue['name'];
+ }else{
+ $tempHtml .= ''.$dialogue['name'];
+ }
+ $tempHtml .= '
';
+ $tempHtml .= '
'.$sentence.'
';
+ $tempHtml .= '
';
+ return $tempHtml;
+ }
+ private function loadChatHeaderImg($castName)
+ {
+ foreach($this->dialogue['roles'] as $cast)
+ {
+ if($cast['name'] == $castName)
+ {
+ return $cast['img'];
+ }
+ }
+ return false; // If not match
+ }
+} // EOF
+?>
\ No newline at end of file