browser_app_base 0.0.6 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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