browser_app_base 0.0.6 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ee14b20cd2c842b0c470d9b96f31549ae576912a5e79afcbb4b44b35d3cfc740
4
- data.tar.gz: 746081592fef24334ae14f50fbcddb672fa29103b800ea8bd84048711ff0ec9e
3
+ metadata.gz: c449614e4619060aa9e9f5799bc67822e61c1f603ff099914aff5e60593828dd
4
+ data.tar.gz: c146b0df93c05a64dceb9d6987895635bef0d733f9421581aa421c51d7077fd9
5
5
  SHA512:
6
- metadata.gz: a0360895d392e1fdbf2930c73c82ba09a8551ea15014ee30f5e71393b4b04d48ea52773f174cc4eb884eea85574e338bf0d8661362c3c4f1cda8512429466f4c
7
- data.tar.gz: a48af4eeb30f310d5f601e19a212fb2c4e4239b61952ab33b2cc50d9e2392dc14b7fec672abc64507aadf55d415831cb194048af9c8903e7fb7e604476895441
6
+ metadata.gz: ed31b5268858c2ac45a01f20924cfe569c0f360797bfad8650a37cf07eff9452b229dbc30ecd0b3200ac5ebcbddc20fcca8f485d4a49440573ee0c6c6a6b7cd2
7
+ data.tar.gz: 00fa73805f8d27f12464fea9bee92720c9303960890e23a02d804f060b6e1429f5b9b02c0dc58ff1bd0ae90ffd4f8ed38c918bdc45e843e203f68563dbce9009
data/.vscode/launch.json CHANGED
@@ -5,10 +5,16 @@
5
5
  "version": "0.2.0",
6
6
  "configurations": [
7
7
  {
8
- "name": "Debug Local File",
8
+ "name": "Debug create_browser_app.rb",
9
9
  "type": "Ruby",
10
10
  "request": "launch",
11
- "cwd": "${workspaceRoot}/lib/template/",
11
+ "program": "${workspaceRoot}/bin/create_browser_app.rb"
12
+ },
13
+ {
14
+ "name": "Debug start.rb",
15
+ "type": "Ruby",
16
+ "request": "launch",
17
+ "cwd": "${workspaceRoot}/lib/template",
12
18
  "program": "${workspaceRoot}/lib/template/start.rb"
13
19
  }
14
20
  ]
data/README.md CHANGED
@@ -58,8 +58,50 @@ ui application sample
58
58
 
59
59
  ## Start application
60
60
 
61
- $ cd ~/test/
62
- $ ruby start.rb
61
+ ```shell
62
+ $ /tmp/test/bin/start_my_app.rb
63
+ ```
64
+
65
+ ## browser setting
66
+
67
+ config/browser.json
68
+ Set the path for your Windows or Linux Chrome browser
69
+
70
+ ```json
71
+ {
72
+ "chrome_win": "start chrome",
73
+ "chrome_linux": "/bin/google-chrome"
74
+ }
75
+ ```
76
+
77
+ ## Send a message from your browser application to your ruby application
78
+
79
+ Use the send_message function
80
+
81
+ main.js sample
82
+ ```javascript
83
+ $("#exec").click(function () {
84
+ send_message("exec:" + $("#upFile").val());
85
+ });
86
+
87
+ ```
88
+
89
+ ## Send a message from the ruby application to the browser application
90
+
91
+ Use the app_send function
92
+
93
+ my_app_sample.rb sample
94
+ ```ruby
95
+ class MyApp < AppMainBase
96
+ def start(argv)
97
+ # popup message
98
+ app_send("popup:message string")
99
+
100
+ # log message
101
+ yield "log message"
102
+ end
103
+ end
104
+ ```
63
105
 
64
106
  ## Development
65
107
 
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "fileutils"
4
+ require "facter"
5
+ require "tmpdir"
6
+
7
+ # tmpdirディレクトリにコピー
8
+ dir = File.dirname(File.expand_path(__FILE__)) + "/../"
9
+ Dir.mktmpdir { |tmpdir|
10
+ puts tmpdir
11
+ Dir.glob("#{dir}/lib/*") do |f|
12
+ puts "#{f} => #{tmpdir}"
13
+ FileUtils.cp_r f, "#{tmpdir}"
14
+ end
15
+
16
+ FileUtils.cd "#{tmpdir}"
17
+ kernel = Facter.value(:kernel)
18
+ if kernel == "windows"
19
+ system "rubyw ./start.rb"
20
+ elsif kernel == "Linux"
21
+ system "ruby ./start.rb"
22
+ else
23
+ system "ruby ./start.rb"
24
+ end
25
+ }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BrowserAppBase
4
- VERSION = "0.0.6"
4
+ VERSION = "0.1.0"
5
5
  end
@@ -37,28 +37,33 @@ module BrowserAppBase
37
37
  puts "create application base #{dir}"
38
38
 
39
39
  FileUtils.mkdir_p dir
40
+ FileUtils.mkdir_p dir + "/lib/"
41
+ FileUtils.mkdir_p dir + "/bin/"
40
42
 
41
- path = File.dirname(File.expand_path(__FILE__))
42
- Dir.glob("#{path}/template/*") do |f|
43
- puts "#{f} => #{dir}"
44
- FileUtils.cp_r f, "#{dir}/"
43
+ path = File.dirname(File.expand_path(__FILE__)) + "/../"
44
+ Dir.glob("#{path}/lib/template/*") do |f|
45
+ puts "#{f} => #{dir}/lib"
46
+ FileUtils.cp_r f, "#{dir}/lib"
45
47
  end
46
48
 
47
49
  if app
48
50
  app_file = get_app_file(app)
49
51
 
52
+ puts "#{path}/bin/start_sample.rb #{dir}/bin/start_#{app_file}"
53
+ FileUtils.cp_r "#{path}/bin/start_sample.rb", "#{dir}/bin/start_#{app_file}"
54
+
50
55
  load_app = <<"EOS"
51
56
  require '#{app_file}'
52
57
  $app = #{get_app_name(app)}.new
53
58
  EOS
54
59
 
55
- File.open("#{dir}/app_load.rb", "w") do |f|
60
+ File.open("#{dir}/lib/app_load.rb", "w") do |f|
56
61
  f.write load_app
57
62
  end
58
63
 
59
64
  puts "create #{app_file}"
60
- new_file = "#{dir}/#{app_file}"
61
- FileUtils.cp("#{dir}/my_app_sample.rb", new_file)
65
+ new_file = "#{dir}/lib/#{app_file}"
66
+ FileUtils.cp("#{dir}/lib/my_app_sample.rb", new_file)
62
67
  buf = File.binread(new_file)
63
68
  File.binwrite(new_file, buf.gsub(/MyApp/, get_app_name(app)))
64
69
  end
@@ -1,7 +1,7 @@
1
1
  [
2
2
  {
3
3
  "name": "name1",
4
- "value": "value1",
4
+ "value": "value1 2 3 4",
5
5
  "type": "input",
6
6
  "select": "",
7
7
  "description": "設定項目1"
@@ -15,7 +15,7 @@
15
15
  },
16
16
  {
17
17
  "name": "name3",
18
- "value": "1",
18
+ "value": "2",
19
19
  "type": "select",
20
20
  "select": [
21
21
  "1",
@@ -8,8 +8,20 @@ require "json"
8
8
  require "./server"
9
9
  require "./wsserver"
10
10
 
11
+ temp_dir = ENV["temp"]
12
+ temp_dir = "/tmp" if temp_dir == nil
13
+ puts "temp_dir=#{temp_dir}"
14
+ access_log = File.new("#{temp_dir}/logs/sinatra.log", "a+")
15
+ access_log.sync = true
16
+ use Rack::CommonLogger, access_log
17
+
11
18
  get "/" do
12
- File.read("index.html")
19
+ File.read("html/index.html")
20
+ end
21
+
22
+ get "*.html" do |file|
23
+ content_type "text/html", :charset => "utf-8"
24
+ File.read "./html/#{file}.html"
13
25
  end
14
26
 
15
27
  get "/css/:name.css" do
@@ -30,6 +42,21 @@ get "/config/*.*" do |file, ext|
30
42
  File.read "config/#{file}.#{ext}"
31
43
  end
32
44
 
45
+ post "/history/*.*" do |file, ext|
46
+ content_type "text/json", :charset => "utf-8"
47
+ puts "#{file}.#{ext}"
48
+ p = params[:param1]
49
+ buf = File.read "history/#{file}.#{ext}"
50
+ data = eval(buf)
51
+ if data != nil
52
+ if p != ""
53
+ JSON.generate data.find_all { |d| d =~ Regexp.new(p) }
54
+ else
55
+ JSON.generate data
56
+ end
57
+ end
58
+ end
59
+
33
60
  get "/open_dialog" do
34
61
  dialog_html = <<'EOS'
35
62
  <!DOCTYPE html>
@@ -65,7 +92,7 @@ end
65
92
 
66
93
  configure do
67
94
  set :DoNotReverseLookup, true
68
- set :logging, false
95
+ set :logging, true
69
96
  set :default_encoding, "utf-8"
70
97
  set :server, :thin
71
98
 
@@ -74,6 +101,6 @@ configure do
74
101
 
75
102
  end
76
103
 
77
- #\ --port 54068
104
+ #\ --port 36809
78
105
 
79
106
  run Sinatra::Application
@@ -1,6 +1,6 @@
1
1
  body {
2
2
  color: #000000;
3
- background-color: #cac3ec4f;
3
+ background-color: #cac3ec4f;
4
4
  overflow: hidden;
5
5
  font-size: 12px;
6
6
  }
@@ -8,9 +8,12 @@ body {
8
8
  hr {
9
9
  color: #ffffff;
10
10
  background-color: #000000;
11
- height: 1px; /* 線の太さ */
12
- border: 1px; /* 枠の太さ */
13
- border-style: solid; /* 枠の種類 */
11
+ height: 1px;
12
+ /* 線の太さ */
13
+ border: 1px;
14
+ /* 枠の太さ */
15
+ border-style: solid;
16
+ /* 枠の種類 */
14
17
  }
15
18
 
16
19
  .error {
@@ -19,7 +22,7 @@ hr {
19
22
 
20
23
  .outarea {
21
24
  background-color: #FFFFFF;
22
- margin: 5px;
25
+ margin: 5px;
23
26
  padding: 5px;
24
27
  width: 95vw;
25
28
  height: 50vh;
@@ -28,15 +31,15 @@ hr {
28
31
 
29
32
  .inarea {
30
33
  border: thin solid #000000;
31
- margin: 5px;
34
+ margin: 5px;
32
35
  padding: 5px;
33
36
  width: 95%;
34
37
  }
35
38
 
36
39
  input.long {
37
40
  width: 90%;
38
- background-color: #FAFAFA;
39
- margin: 5px;
41
+ background-color: #FAFAFA;
42
+ margin: 5px;
40
43
  padding: 5px;
41
44
  }
42
45
 
@@ -63,12 +66,21 @@ textarea.long {
63
66
  color: black;
64
67
  }
65
68
 
69
+ .ui-autocomplete.ui-front {
70
+ max-height: 250px;
71
+ overflow-y: auto;
72
+ /* prevent horizontal scrollbar */
73
+ overflow-x: hidden;
74
+ /* add padding to account for vertical scrollbar */
75
+ z-index: 1000 !important;
76
+ }
77
+
66
78
  .ui-dialog {
67
- position: absolute;
68
- top: 0;
69
- left: 0;
70
- padding: .2em;
71
- outline: 0;
79
+ position: absolute;
80
+ top: 0;
81
+ left: 0;
82
+ padding: .2em;
83
+ outline: 0;
72
84
  }
73
85
 
74
86
  .long {
@@ -77,28 +89,36 @@ textarea.long {
77
89
 
78
90
  #setting_dialog {
79
91
  color: #796fe9;
80
- background-color: #000000;
92
+ background-color: #000000;
81
93
  }
82
94
 
83
95
  .setting_name {
84
96
  width: 200px;
85
97
  color: #796fe9;
86
- background-color: #000000;
98
+ background-color: #000000;
87
99
  }
88
100
 
89
101
  .setting_value {
90
102
  width: 300px;
91
103
  color: #796fe9;
92
- background-color: #000000;
104
+ background-color: #000000;
93
105
  }
94
106
 
95
107
  .setting_checkbox {
96
108
  color: #796fe9;
97
- background-color: #000000;
109
+ background-color: #000000;
98
110
  }
99
111
 
100
112
  ul.log {
101
- list-style-type: decimal;
113
+ list-style-type: decimal;
102
114
  font-size: 12px;
103
115
  color: #5d0a94;
116
+ }
117
+
118
+ input[type="search"] {
119
+ -webkit-appearance: searchfield;
120
+ }
121
+
122
+ input[type="search"]::-webkit-search-cancel-button {
123
+ -webkit-appearance: searchfield-cancel-button;
104
124
  }
File without changes
@@ -11,12 +11,15 @@
11
11
  <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
12
12
  <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
13
13
 
14
- <script src="http://localhost:54068/js/main.js"></script>
15
- <link rel="stylesheet" href="http://localhost:54068/css/index.css" type="text/css">
14
+ <script src="http://localhost:36809/js/main.js"></script>
15
+ <link rel="stylesheet" href="http://localhost:36809/css/index.css" type="text/css">
16
16
  </head>
17
17
 
18
18
  <body>
19
- <h4>サンプル</h4>
19
+ <div id="msg_dialog" style="display:none;">
20
+ <div id="msg_text">message</div>
21
+ </div>
22
+ <h4>RubyAppBase</h4>
20
23
  <hr>
21
24
  <table>
22
25
  <tr>
@@ -36,21 +39,21 @@
36
39
  </table>
37
40
 
38
41
  <div id="dialog1" style="display:none;">
39
- <input class="inarea" type="text" name="search_str" id="search_str">
42
+ <input class="inarea" type="search" name="search_str" id="search_str">
40
43
  </div>
41
44
  <table>
42
45
  <tr>
43
- <td class="long"><input class="inarea" type="text" id="upFile" name="upFile"></td>
46
+ <td class="long"><input class="inarea" type="search" id="upFile" name="upFile"></td>
44
47
  <td><input type="button" id="select_file" value="ファイル選択" /></td>
45
48
  </tr>
46
49
  </table>
47
50
 
48
51
  <div id="dialog2" style="display:none;">
49
- <input class="inarea" type="text" name="search_str2" id="search_str2">
52
+ <input class="inarea" type="search" name="search_str2" id="search_str2">
50
53
  </div>
51
54
  <table>
52
55
  <tr>
53
- <td class="long"><input class="inarea" type="text" id="upDir" name="upDir"></td>
56
+ <td class="long"><input class="inarea" type="search" id="upDir" name="upDir"></td>
54
57
  <td><input type="button" id="select_dir" value="フォルダ選択" /></td>
55
58
  </tr>
56
59
  </table>
@@ -0,0 +1,85 @@
1
+ <!DOCTYPE html>
2
+ <html lang="ja">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <title>modalをcomponentで作る</title>
7
+ </head>
8
+
9
+ <style>
10
+ #content {
11
+ z-index: 10;
12
+ width: 50%;
13
+ padding: 1em;
14
+ background: #fff;
15
+ }
16
+
17
+ #overlay {
18
+ /* 要素を重ねた時の順番 */
19
+
20
+ z-index: 1;
21
+
22
+ /* 画面全体を覆う設定 */
23
+ position: fixed;
24
+ top: 0;
25
+ left: 0;
26
+ width: 100%;
27
+ height: 100%;
28
+ background-color: rgba(0, 0, 0, 0.5);
29
+
30
+ /* 画面の中央に要素を表示させる設定 */
31
+ display: flex;
32
+ align-items: center;
33
+ justify-content: center;
34
+
35
+ }
36
+ </style>
37
+
38
+ <body>
39
+ <div id="app">
40
+
41
+ <button v-on:click="openModal">Click</button>
42
+
43
+ <open-modal v-show="showContent" v-on:from-child="closeModal">slotからモーダルウィンドウへ</open-modal>
44
+
45
+ </div>
46
+
47
+ <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
48
+ <script>
49
+ Vue.component('open-modal', {
50
+ template: `
51
+ <div id="overlay" v-on:click="clickEvent">
52
+ <div id="content"  v-on:click="stopEvent">
53
+ <p><slot></slot></p>
54
+ <button v-on:click="clickEvent">close</button>
55
+ </div>
56
+ </div>
57
+ `,
58
+ methods: {
59
+ clickEvent: function () {
60
+ this.$emit('from-child')
61
+ },
62
+ stopEvent: function () {
63
+ event.stopPropagation()
64
+ }
65
+ }
66
+ })
67
+
68
+ new Vue({
69
+ el: '#app',
70
+ data: {
71
+ showContent: false
72
+ },
73
+ methods: {
74
+ openModal: function () {
75
+ this.showContent = true
76
+ },
77
+ closeModal: function () {
78
+ this.showContent = false
79
+ },
80
+ }
81
+ })
82
+ </script>
83
+ </body>
84
+
85
+ </html>
@@ -3,8 +3,38 @@
3
3
  var $ws = null;
4
4
  var $auto_scroll = true;
5
5
  var dialog = null;
6
+ var dialog_timeout = null;
6
7
 
7
- function open_dialog(msg) {
8
+ function open_dialog(msg, timeout = 0) {
9
+ console.log("msg=" + msg);
10
+ $("#msg_text").html(msg);
11
+ d = $("#msg_dialog").dialog({
12
+ modal: true
13
+ , show: "slide" //表示時のアニメーション
14
+ , hide: "slide" //閉じた時のアニメーション
15
+ , title: "Message" //ダイアログのタイトル
16
+ , width: 500 //ダイアログの横幅
17
+ , height: 300 //ダイアログの高さ
18
+ , resizable: true //リサイズ可
19
+ , closeOnEscape: false //[ESC]キーで閉じられなくする
20
+ , draggable: true //ダイアログの移動を可に
21
+ , buttons: {
22
+ "OK": function () { //Cancelボタン
23
+ if (dialog_timeout != null) {
24
+ clearTimeout(dialog_timeout);
25
+ }
26
+ $(this).dialog("close");
27
+ }
28
+ }
29
+ });
30
+ if (timeout != 0) {
31
+ dialog_timeout = setTimeout(function () {
32
+ d.dialog("close");
33
+ }, timeout);
34
+ }
35
+ }
36
+
37
+ function open_dialog_org(msg) {
8
38
  var top = window.screenTop + 10;
9
39
  var left = window.screenLeft + 10;
10
40
  if (dialog != null) {
@@ -37,13 +67,18 @@ function server_connect(url) {
37
67
 
38
68
  if (evt.data.match(/^startup:/)) {
39
69
  file_name = evt.data.replace(/^startup:/, "");
40
- //alert(file_name);
41
70
  }
42
71
  else if (evt.data.match(/^app_end:normal/)) {
43
72
  open_dialog("終了しました");
44
73
  }
74
+ else if (evt.data.match(/^app_end:stop/)) {
75
+ open_dialog("中止しました");
76
+ }
45
77
  else if (evt.data.match(/^app_end:error/)) {
46
78
  open_dialog("<font color='red'>エラーが発生しました</font>");
79
+ }
80
+ else if (evt.data.match(/^popup:/)) {
81
+ open_dialog(evt.data.replace(/^popup:/, ""), 3000);
47
82
  } else {
48
83
  var log = "<li>" + evt.data + "</li>";
49
84
  $('#log').append(log);
@@ -80,7 +115,7 @@ function autocomp(id, file_kind) {
80
115
  },
81
116
  source: function (req, resp) {
82
117
  $.ajax({
83
- url: "http://localhost:54068/search?path=" + $("#" + id).val() + "&kind=" + file_kind,
118
+ url: "http://localhost:36809/search?path=" + $("#" + id).val() + "&kind=" + file_kind,
84
119
  type: "GET",
85
120
  cache: false,
86
121
  dataType: "json",
@@ -102,11 +137,44 @@ function autocomp(id, file_kind) {
102
137
  });
103
138
  }
104
139
 
140
+ function autocomp_history(id, file_name) {
141
+ $("#" + id).autocomplete({
142
+ autoFocus: true,
143
+ minLength: 0,
144
+ delay: 0,
145
+ select: function (event, ui) {
146
+ jQuery("#" + id).val(ui.item.value);
147
+ $(this).keydown();
148
+ },
149
+ source: function (req, resp) {
150
+ $.ajax({
151
+ url: "http://localhost:36809/history/" + file_name,
152
+ type: "POST",
153
+ cache: false,
154
+ dataType: "json",
155
+ data: {
156
+ param1: req.term
157
+ },
158
+ success: function (o) {
159
+ resp(o);
160
+ },
161
+ error: function (xhr, ts, err) {
162
+ resp(['']);
163
+ }
164
+ });
165
+
166
+ }
167
+ }).focus(function () {
168
+ $(this).keydown();
169
+ });
170
+ }
171
+
105
172
  function select_file_dialog(search_id, file_kind, dialog_id, select_file, file_name) {
106
173
  $("#" + select_file).click(function () {
107
174
  autocomp(search_id, file_kind);
108
175
  $(".ui-autocomplete").css("z-index", 1000);
109
- $("#" + search_id).val("/");
176
+ console.log("name=" + $("#" + file_name).val());
177
+ $("#" + search_id).val($("#" + file_name).val());
110
178
  $("#" + dialog_id).dialog({
111
179
  modal: true
112
180
  , show: "slide" //表示時のアニメーション
@@ -141,7 +209,7 @@ function setting_dialog(open_id, dialog_id, json_file) {
141
209
  if (s[i].type == "input") {
142
210
  var h = "<table><tr>"
143
211
  + "<td class='setting_name'>" + s[i].description + "</td>"
144
- + "<td><input class='setting_value' type='text' " + "id=" + s[i].name + "_value " + "value=" + s[i].value + ">"
212
+ + "<td><input class='setting_value' type='text' " + "id=" + s[i].name + "_value " + "value=" + "'" + s[i].value + "'" + ">"
145
213
  + "</td></tr></table>"
146
214
  $("dl#wrap").append(h);
147
215
  } else if (s[i].type == "checkbox") {
@@ -254,20 +322,25 @@ function openFile(file) {
254
322
 
255
323
  // 起動時の処理
256
324
  $(document).ready(function () {
257
- // サーバに接続
258
- server_connect("ws://localhost:54068/wsserver")
325
+
326
+ window.onload = function (e) {
327
+ console.log("onload");
328
+ // サーバに接続
329
+ server_connect("ws://localhost:36809/wsserver")
330
+ }
331
+
259
332
  // ウインドウサイズ
260
333
  var width = 800;
261
334
  var height = 600;
262
- $(window).resize(function() {
263
- $(".outarea").height( $(window).height() - 250 );
335
+ $(window).resize(function () {
336
+ $(".outarea").height($(window).height() - 220);
264
337
  });
265
338
  // ウインドウの位置
266
339
  $(function () {
267
340
  window.resizeTo(width, height);
268
341
  window.moveTo((window.screen.width / 2) - (width / 2), (screen.height / 2) - (height / 2));
269
342
  //window.moveTo(0,0);
270
- $(".outarea").height( $(window).height() - 250 );
343
+ $(".outarea").height($(window).height() - 220);
271
344
  });
272
345
 
273
346
  $('.outarea').scroll(function () {
@@ -300,5 +373,7 @@ $(document).ready(function () {
300
373
 
301
374
  setting_dialog("setting", "setting_dialog", "config/setting.json");
302
375
 
376
+ autocomp_history("upFile", "history.json")
377
+
303
378
  });
304
379
 
@@ -10,8 +10,16 @@ class MyApp < AppMainBase
10
10
  argv.each do |v|
11
11
  yield v if block_given?
12
12
  end
13
+
14
+ # Browserにメッセージ送信
15
+ app_send("popup:start app #{argv[0]}")
16
+
17
+ # 履歴の保存
18
+ add_history("history.json", argv[0])
19
+
13
20
  while true
14
21
  yield Time.now.to_s if block_given?
22
+ puts Time.now.to_s
15
23
  yield @config["name1"]
16
24
  sleep 1
17
25
  break if @abort
@@ -5,6 +5,17 @@ class AppMainBase
5
5
  @aboet = false
6
6
  @exec = false
7
7
  @suspend = false
8
+ @ws = nil
9
+ end
10
+
11
+ def app_send(str)
12
+ if @ws != nil
13
+ @ws.send(str)
14
+ end
15
+ end
16
+
17
+ def set_ws(ws)
18
+ @ws = ws
8
19
  end
9
20
 
10
21
  def set_config(config)
@@ -27,6 +38,22 @@ class AppMainBase
27
38
  def resume()
28
39
  @suspend = false
29
40
  end
41
+
42
+ # 履歴の保存
43
+ def add_history(file, history_data, max = 10)
44
+ buf = File.read "history/#{file}"
45
+ data = eval(buf)
46
+ if data == nil
47
+ data = []
48
+ end
49
+ if history_data.to_s != ""
50
+ data.prepend history_data
51
+ end
52
+ data = data.uniq[0..max - 1]
53
+ File.open("history/#{file}", "w") do |f|
54
+ f.write JSON.pretty_generate data
55
+ end
56
+ end
30
57
  end
31
58
 
32
59
  require "app_load.rb"
@@ -10,6 +10,52 @@ require "kconv"
10
10
  require "json"
11
11
  require "facter"
12
12
 
13
+ # ログ出力
14
+ module Output
15
+ def self.console_and_file(output_file, stdout = true)
16
+ begin
17
+ defout = File.new(output_file, "a+")
18
+ rescue
19
+ puts $!
20
+ puts $@
21
+ return nil
22
+ end
23
+ class << defout
24
+ alias_method :write_org, :write
25
+
26
+ def initialize(stdout)
27
+ @stdout = false
28
+ end
29
+
30
+ attr_accessor :stdout
31
+
32
+ def puts(str)
33
+ STDOUT.write(str.to_s + "\n") if @stdout
34
+ self.write_org(str.to_s + "\n")
35
+ self.flush
36
+ end
37
+
38
+ def write(str)
39
+ STDOUT.write(str) if @stdout
40
+ self.write_org(str)
41
+ self.flush
42
+ end
43
+ end
44
+ $stdout = defout
45
+ $stdout.stdout = stdout
46
+ end
47
+ end
48
+
49
+ # ディレクトリ移動
50
+ dir = File.dirname(File.expand_path(__FILE__))
51
+ FileUtils.cd dir
52
+
53
+ temp_dir = ENV["temp"]
54
+ temp_dir = "/tmp" if temp_dir == nil
55
+ puts "temp_dir=#{temp_dir}"
56
+ FileUtils.mkdir_p("#{temp_dir}/logs")
57
+ Output.console_and_file("#{temp_dir}/logs/app.log", true)
58
+
13
59
  # 空きポートを取得
14
60
  def get_unused_port
15
61
  s = TCPServer.open(0)
@@ -33,26 +79,45 @@ buf.gsub!(/localhost:[0-9]+\//, "localhost:#{port}/")
33
79
  File.binwrite("js/main.js", buf)
34
80
 
35
81
  # index.htaの編集
36
- buf = File.binread("index.html").toutf8
82
+ buf = File.binread("html/index.html").toutf8
37
83
  buf.gsub!(/localhost:[0-9]+\//, "localhost:#{port}/")
38
- File.binwrite("index.html", buf)
39
-
40
- Thread.start {
41
- puts "start browser"
42
- json_file = File.dirname(File.expand_path(__FILE__)) + "/config/browser.json"
43
- json = JSON.parse(File.read json_file)
44
- puts json
45
- kernel = Facter.value(:kernel)
46
- if kernel == "windows"
47
- browser = json["chrome_win"]
48
- elsif kernel == "Linux"
49
- browser = json["chrome_linux"]
50
- else
51
- browser = json["chrome_win"]
52
- end
53
- browser += " -app=http://localhost:#{port}"
54
- puts browser
55
- system browser
56
- }
84
+ File.binwrite("html/index.html", buf)
57
85
 
58
- Rack::Server.start
86
+ begin
87
+ Thread.start {
88
+ puts "wait start web server"
89
+ while true
90
+ begin
91
+ s = TCPSocket.open("localhost", port)
92
+ s.close
93
+ break
94
+ rescue
95
+ puts $!
96
+ sleep 0.1
97
+ end
98
+ end
99
+
100
+ puts "start browser"
101
+ json_file = File.dirname(File.expand_path(__FILE__)) + "/config/browser.json"
102
+ json = JSON.parse(File.read json_file)
103
+ puts json
104
+ kernel = Facter.value(:kernel)
105
+ if kernel == "windows"
106
+ browser = json["chrome_win"]
107
+ elsif kernel == "Linux"
108
+ browser = json["chrome_linux"]
109
+ else
110
+ browser = json["chrome_win"]
111
+ end
112
+ browser += " -app=http://localhost:#{port}"
113
+ puts browser
114
+ system browser
115
+ }
116
+
117
+ # start web server
118
+ Rack::Server.start
119
+ rescue
120
+ puts $!
121
+ puts $@
122
+ exit
123
+ end
@@ -1,6 +1,7 @@
1
1
  require "./server_app_base"
2
2
  require "json"
3
3
  require "cgi"
4
+ require "thread"
4
5
 
5
6
  def config_json_hash(json)
6
7
  config = {}
@@ -10,8 +11,23 @@ def config_json_hash(json)
10
11
  return config
11
12
  end
12
13
 
14
+ $ws_exit_thread = nil
15
+
13
16
  class WsServer < Sinatra::Base
14
- $ws_list = []
17
+ def initialize
18
+ super
19
+ @ws_list = []
20
+ @ws_lock = Mutex.new
21
+ end
22
+
23
+ def ws_send(str)
24
+ @ws_lock.synchronize do
25
+ if @ws_list[0] != nil
26
+ @ws_list[0].send(str)
27
+ end
28
+ end
29
+ end
30
+
15
31
  json_config = nil
16
32
  exec_thread = nil
17
33
  get "" do
@@ -20,28 +36,38 @@ class WsServer < Sinatra::Base
20
36
  else
21
37
  request.websocket do |ws|
22
38
  ws.onopen do
23
- ws.send("startup:#{$startup_file}")
24
- $ws_list << ws
39
+ puts "ws.open"
40
+ @ws_lock.synchronize do
41
+ @ws_list << ws
42
+ $app.set_ws(ws)
43
+ pp "ws=#{ws}"
44
+ end
45
+ ws_send("startup:#{$startup_file}")
46
+ puts "ws_exit_thread=#{$ws_exit_thread}"
47
+ if $ws_exit_thread != nil
48
+ puts "ws_exit_thread kill"
49
+ Thread.kill $ws_exit_thread
50
+ end
25
51
  end
26
52
  ws.onmessage do |msg|
27
53
  puts msg
54
+ json = JSON.parse(File.read("config/setting.json"))
55
+ json_config = config_json_hash(json)
56
+ $app.set_config(json_config)
28
57
  if msg =~ /^exec:/
29
58
  if exec_thread == nil
30
- json = JSON.parse(File.read("config/setting.json"))
31
- json_config = config_json_hash(json)
32
- $app.set_config(json_config)
33
59
  argv = msg.gsub(/^exec:/, "")
34
60
  exec_thread = Thread.new {
35
61
  begin
36
62
  $app.start(argv.split(",")) do |out|
37
- ws.send(out)
63
+ ws_send(out)
38
64
  end
39
- ws.send("app_end:normal")
65
+ ws_send("app_end:normal")
40
66
  rescue
41
67
  puts $!
42
68
  puts $@
43
69
  puts "app_end:err"
44
- ws.send("app_end:error")
70
+ ws_send("app_end:error")
45
71
  ensure
46
72
  puts "exit thread"
47
73
  exec_thread = nil
@@ -49,11 +75,13 @@ class WsServer < Sinatra::Base
49
75
  }
50
76
  else
51
77
  puts "app_end:err"
52
- ws.send("app_end:error")
78
+ ws_send("app_end:error")
53
79
  end
54
80
  end
55
81
  if msg =~ /^stop/
56
82
  if exec_thread
83
+ Thread.kill exec_thread
84
+ ws_send("app_end:stop")
57
85
  $app.stop
58
86
  end
59
87
  end
@@ -83,23 +111,27 @@ class WsServer < Sinatra::Base
83
111
  }
84
112
  end
85
113
 
114
+ # アプリケーション終了
86
115
  if msg == "exit"
87
- unless ENV["OCRA"] == "true"
88
- halt
89
- #exit
90
- end
116
+ #halt
117
+ exit
91
118
  end
92
119
  end
120
+
121
+ # close websocket
93
122
  ws.onclose do
94
123
  puts "websocket closed"
95
- $ws_list.delete(ws)
96
- puts $ws_list.size
97
- if $ws_list.size == 0
98
- puts ENV["OCRA"]
99
- unless ENV["OCRA"] == "true"
124
+ @ws_lock.synchronize do
125
+ @ws_list.delete(ws)
126
+ end
127
+ puts @ws_list.size
128
+ if @ws_list.size == 0
129
+ $ws_exit_thread = Thread.start {
130
+ sleep 1
100
131
  #halt
101
132
  exit
102
- end
133
+ }
134
+ puts "ws_exit_thread=#{$ws_exit_thread}"
103
135
  end
104
136
  end
105
137
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: browser_app_base
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - masataka kuwayama
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-26 00:00:00.000000000 Z
11
+ date: 2022-01-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sinatra
@@ -99,6 +99,7 @@ email:
99
99
  - masataka.kuwayama@gmail.com
100
100
  executables:
101
101
  - create_browser_app.rb
102
+ - start_sample.rb
102
103
  extensions: []
103
104
  extra_rdoc_files: []
104
105
  files:
@@ -110,6 +111,7 @@ files:
110
111
  - README.md
111
112
  - Rakefile
112
113
  - bin/create_browser_app.rb
114
+ - bin/start_sample.rb
113
115
  - browser_app_base.gemspec
114
116
  - lib/browser_app_base.rb
115
117
  - lib/browser_app_base/version.rb
@@ -118,7 +120,9 @@ files:
118
120
  - lib/template/config/browser.json
119
121
  - lib/template/config/setting.json
120
122
  - lib/template/css/index.css
121
- - lib/template/index.html
123
+ - lib/template/history/history.json
124
+ - lib/template/html/index.html
125
+ - lib/template/html/test.html
122
126
  - lib/template/js/main.js
123
127
  - lib/template/my_app_sample.rb
124
128
  - lib/template/server.rb